Test Failed
Branch develop (db5506)
by Felipe
03:46
created

FunctionsController::doEdit()   F

Complexity

Conditions 42
Paths > 20000

Size

Total Lines 229
Code Lines 164

Duplication

Lines 83
Ratio 36.24 %

Importance

Changes 0
Metric Value
cc 42
eloc 164
nc 737281
nop 1
dl 83
loc 229
rs 2
c 0
b 0
f 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
namespace PHPPgAdmin\Controller;
4
5
use \PHPPgAdmin\Decorators\Decorator;
6
7
/**
8
 * Base controller class
9
 */
10
class FunctionsController extends BaseController
11
{
12
    public $_name       = 'FunctionsController';
13
    public $table_place = 'functions-functions';
14
15
    public function render()
0 ignored issues
show
Coding Style introduced by
render uses the super-global variable $_POST which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
16
    {
17
        $conf = $this->conf;
0 ignored issues
show
Unused Code introduced by
The assignment to $conf is dead and can be removed.
Loading history...
18
        $misc = $this->misc;
19
        $lang = $this->lang;
20
21
        $action = $this->action;
22
        if ($action == 'tree') {
23
            return $this->doTree();
24
        }
25
        $data = $misc->getDatabaseAccessor();
0 ignored issues
show
Unused Code introduced by
The assignment to $data is dead and can be removed.
Loading history...
26
27
        $this->printHeader($lang['strfunctions'], null, true, 'header_datatables.twig');
28
        $this->printBody();
29
30
        switch ($action) {
31
            case 'save_create':
32
                if (isset($_POST['cancel'])) {
33
                    $this->doDefault();
34
                } else {
35
                    $this->doSaveCreate();
36
                }
37
38
                break;
39
            case 'create':
40
                $this->doCreate();
41
                break;
42
            case 'drop':
43
                if (isset($_POST['drop'])) {
44
                    $this->doDrop(false);
45
                } else {
46
                    $this->doDefault();
47
                }
48
49
                break;
50
            case 'confirm_drop':
51
                $this->doDrop(true);
52
                break;
53
            case 'save_edit':
54
                if (isset($_POST['cancel'])) {
55
                    $this->doDefault();
56
                } else {
57
                    $this->doSaveEdit();
58
                }
59
60
                break;
61
            case 'edit':
62
                $this->doEdit();
63
                break;
64
            case 'properties':
65
                $this->doProperties();
66
                break;
67
            default:
68
                $this->doDefault();
69
                break;
70
        }
71
72
        $this->printFooter();
73
    }
74
75
    /**
76
     * Show default list of functions in the database
77
     */
78
    public function doDefault($msg = '')
0 ignored issues
show
Coding Style introduced by
doDefault uses the super-global variable $_REQUEST which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
79
    {
80
        $conf = $this->conf;
81
        $misc = $this->misc;
82
        $lang = $this->lang;
83
        $data = $misc->getDatabaseAccessor();
84
85
        $this->printTrail('schema');
86
        $this->printTabs('schema', 'functions');
87
        $this->printMsg($msg);
88
89
        $funcs = $data->getFunctions();
90
91
        $columns = [
92
            'function'     => [
93
                'title' => $lang['strfunction'],
94
                'field' => Decorator::field('proproto'),
95
                'url'   => SUBFOLDER . "/redirect/function?action=properties&amp;{$misc->href}&amp;",
96
                'vars'  => ['function' => 'proproto', 'function_oid' => 'prooid'],
97
            ],
98
            'returns'      => [
99
                'title' => $lang['strreturns'],
100
                'field' => Decorator::field('proreturns'),
101
            ],
102
            'owner'        => [
103
                'title' => $lang['strowner'],
104
                'field' => Decorator::field('proowner'),
105
            ],
106
            'proglanguage' => [
107
                'title' => $lang['strproglanguage'],
108
                'field' => Decorator::field('prolanguage'),
109
            ],
110
            'actions'      => [
111
                'title' => $lang['stractions'],
112
            ],
113
            'comment'      => [
114
                'title' => $lang['strcomment'],
115
                'field' => Decorator::field('procomment'),
116
            ],
117
        ];
118
119
        $actions = [
120
            'multiactions' => [
121
                'keycols' => ['function' => 'proproto', 'function_oid' => 'prooid'],
122
                'url'     => 'functions.php',
123
            ],
124
            'alter'        => [
125
                'content' => $lang['stralter'],
126
                'attr'    => [
127
                    'href' => [
128
                        'url'     => 'functions.php',
129
                        'urlvars' => [
130
                            'action'       => 'edit',
131
                            'function'     => Decorator::field('proproto'),
132
                            'function_oid' => Decorator::field('prooid'),
133
                        ],
134
                    ],
135
                ],
136
            ],
137
            'drop'         => [
138
                'multiaction' => 'confirm_drop',
139
                'content'     => $lang['strdrop'],
140
                'attr'        => [
141
                    'href' => [
142
                        'url'     => 'functions.php',
143
                        'urlvars' => [
144
                            'action'       => 'confirm_drop',
145
                            'function'     => Decorator::field('proproto'),
146
                            'function_oid' => Decorator::field('prooid'),
147
                        ],
148
                    ],
149
                ],
150
            ],
151
            'privileges'   => [
152
                'content' => $lang['strprivileges'],
153
                'attr'    => [
154
                    'href' => [
155
                        'url'     => 'privileges.php',
156
                        'urlvars' => [
157
                            'subject'      => 'function',
158
                            'function'     => Decorator::field('proproto'),
159
                            'function_oid' => Decorator::field('prooid'),
160
                        ],
161
                    ],
162
                ],
163
            ],
164
        ];
165
166
        echo $this->printTable($funcs, $columns, $actions, $this->table_place, $lang['strnofunctions']);
167
168
        $navlinks = [
169
            'createpl'       => [
170
                'attr'    => [
171
                    'href' => [
172
                        'url'     => 'functions.php',
173
                        'urlvars' => [
174
                            'action'   => 'create',
175
                            'server'   => $_REQUEST['server'],
176
                            'database' => $_REQUEST['database'],
177
                            'schema'   => $_REQUEST['schema'],
178
                        ],
179
                    ],
180
                ],
181
                'content' => $lang['strcreateplfunction'],
182
            ],
183
            'createinternal' => [
184
                'attr'    => [
185
                    'href' => [
186
                        'url'     => 'functions.php',
187
                        'urlvars' => [
188
                            'action'   => 'create',
189
                            'language' => 'internal',
190
                            'server'   => $_REQUEST['server'],
191
                            'database' => $_REQUEST['database'],
192
                            'schema'   => $_REQUEST['schema'],
193
                        ],
194
                    ],
195
                ],
196
                'content' => $lang['strcreateinternalfunction'],
197
            ],
198
            'createc'        => [
199
                'attr'    => [
200
                    'href' => [
201
                        'url'     => 'functions.php',
202
                        'urlvars' => [
203
                            'action'   => 'create',
204
                            'language' => 'C',
205
                            'server'   => $_REQUEST['server'],
206
                            'database' => $_REQUEST['database'],
207
                            'schema'   => $_REQUEST['schema'],
208
                        ],
209
                    ],
210
                ],
211
                'content' => $lang['strcreatecfunction'],
212
            ],
213
        ];
214
215
        $this->printNavLinks($navlinks, 'functions-functions', get_defined_vars());
216
    }
217
218
    /**
219
     * Generate XML for the browser tree.
220
     */
221 View Code Duplication
    public function doTree()
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
222
    {
223
        $conf = $this->conf;
0 ignored issues
show
Unused Code introduced by
The assignment to $conf is dead and can be removed.
Loading history...
224
        $misc = $this->misc;
225
        $lang = $this->lang;
0 ignored issues
show
Unused Code introduced by
The assignment to $lang is dead and can be removed.
Loading history...
226
        $data = $misc->getDatabaseAccessor();
227
228
        $funcs = $data->getFunctions();
229
230
        $proto = Decorator::concat(Decorator::field('proname'), ' (', Decorator::field('proarguments'), ')');
231
232
        $reqvars = $misc->getRequestVars('function');
233
234
        $attrs = [
235
            'text'    => $proto,
236
            'icon'    => 'Function',
237
            'toolTip' => Decorator::field('procomment'),
238
            'action'  => Decorator::redirecturl('redirect.php',
239
                $reqvars,
240
                [
241
                    'action'       => 'properties',
242
                    'function'     => $proto,
243
                    'function_oid' => Decorator::field('prooid'),
244
                ]
245
            ),
246
        ];
247
248
        return $this->printTree($funcs, $attrs, 'functions');
249
    }
250
251
    /**
252
     * Function to save after editing a function
253
     */
254
    public function doSaveEdit()
0 ignored issues
show
Coding Style introduced by
doSaveEdit uses the super-global variable $_POST which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
255
    {
256
        $conf = $this->conf;
0 ignored issues
show
Unused Code introduced by
The assignment to $conf is dead and can be removed.
Loading history...
257
        $misc = $this->misc;
258
        $lang = $this->lang;
259
        $data = $misc->getDatabaseAccessor();
260
261
        $fnlang = strtolower($_POST['original_lang']);
262
263 View Code Duplication
        if ($fnlang == 'c') {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
264
            $def = [$_POST['formObjectFile'], $_POST['formLinkSymbol']];
265
        } elseif ($fnlang == 'internal') {
266
            $def = $_POST['formLinkSymbol'];
267
        } else {
268
            $def = $_POST['formDefinition'];
269
        }
270
        if (!$data->hasFunctionAlterSchema()) {
271
            $_POST['formFuncSchema'] = '';
272
        }
273
274
        $status = $data->setFunction($_POST['function_oid'], $_POST['original_function'], $_POST['formFunction'],
275
            $_POST['original_arguments'], $_POST['original_returns'], $def,
276
            $_POST['original_lang'], $_POST['formProperties'], isset($_POST['original_setof']),
277
            $_POST['original_owner'], $_POST['formFuncOwn'], $_POST['original_schema'],
278
            $_POST['formFuncSchema'], isset($_POST['formCost']) ? $_POST['formCost'] : null,
279
            isset($_POST['formRows']) ? $_POST['formRows'] : 0, $_POST['formComment']);
280
281
        if ($status == 0) {
282
            // If function has had schema altered, need to change to the new schema
283
            // and reload the browser frame.
284
            if (!empty($_POST['formFuncSchema']) && ($_POST['formFuncSchema'] != $_POST['original_schema'])) {
285
                // Jump them to the new function schema
286
                $misc->setCurrentSchema($_POST['formFuncSchema']);
287
                // Force a browser reload
288
                $this->misc->setReloadBrowser(true);
289
            }
290
            $this->doProperties($lang['strfunctionupdated']);
291
        } else {
292
            $this->doEdit($lang['strfunctionupdatedbad']);
293
        }
294
    }
295
296
    /**
297
     * Function to allow editing of a Function
298
     */
299
    public function doEdit($msg = '')
0 ignored issues
show
Coding Style introduced by
doEdit uses the super-global variable $_REQUEST which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
Coding Style introduced by
doEdit uses the super-global variable $_POST which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
300
    {
301
        $conf = $this->conf;
0 ignored issues
show
Unused Code introduced by
The assignment to $conf is dead and can be removed.
Loading history...
302
        $misc = $this->misc;
303
        $lang = $this->lang;
304
        $data = $misc->getDatabaseAccessor();
305
306
        $this->printTrail('function');
307
        $this->printTitle($lang['stralter'], 'pg.function.alter');
308
        $this->printMsg($msg);
309
310
        $fndata = $data->getFunction($_REQUEST['function_oid']);
311
312
        if ($fndata->recordCount() > 0) {
313
            $fndata->fields['proretset'] = $data->phpBool($fndata->fields['proretset']);
314
315
            // Initialise variables
316
            if (!isset($_POST['formDefinition'])) {
317
                $_POST['formDefinition'] = $fndata->fields['prosrc'];
318
            }
319
320
            if (!isset($_POST['formProperties'])) {
321
                $_POST['formProperties'] = $data->getFunctionProperties($fndata->fields);
322
            }
323
324
            if (!isset($_POST['formFunction'])) {
325
                $_POST['formFunction'] = $fndata->fields['proname'];
326
            }
327
328
            if (!isset($_POST['formComment'])) {
329
                $_POST['formComment'] = $fndata->fields['procomment'];
330
            }
331
332
            if (!isset($_POST['formObjectFile'])) {
333
                $_POST['formObjectFile'] = $fndata->fields['probin'];
334
            }
335
336
            if (!isset($_POST['formLinkSymbol'])) {
337
                $_POST['formLinkSymbol'] = $fndata->fields['prosrc'];
338
            }
339
340
            if (!isset($_POST['formFuncOwn'])) {
341
                $_POST['formFuncOwn'] = $fndata->fields['proowner'];
342
            }
343
344
            if (!isset($_POST['formFuncSchema'])) {
345
                $_POST['formFuncSchema'] = $fndata->fields['proschema'];
346
            }
347
348
            if ($data->hasFunctionCosting()) {
349
                if (!isset($_POST['formCost'])) {
350
                    $_POST['formCost'] = $fndata->fields['procost'];
351
                }
352
353
                if (!isset($_POST['formRows'])) {
354
                    $_POST['formRows'] = $fndata->fields['prorows'];
355
                }
356
            }
357
358
            // Deal with named parameters
359 View Code Duplication
            if ($data->hasNamedParams()) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
360
                if (isset($fndata->fields['proallarguments'])) {
361
                    $args_arr = $data->phpArray($fndata->fields['proallarguments']);
362
                } else {
363
                    $args_arr = explode(', ', $fndata->fields['proarguments']);
364
                }
365
                $names_arr = $data->phpArray($fndata->fields['proargnames']);
366
                $modes_arr = $data->phpArray($fndata->fields['proargmodes']);
367
                $args      = '';
368
                $i         = 0;
0 ignored issues
show
Unused Code introduced by
The assignment to $i is dead and can be removed.
Loading history...
369
                for ($i = 0; $i < sizeof($args_arr); $i++) {
0 ignored issues
show
Performance Best Practice introduced by
It seems like you are calling the size function sizeof() as part of the test condition. You might want to compute the size beforehand, and not on each iteration.

If the size of the collection does not change during the iteration, it is generally a good practice to compute it beforehand, and not on each iteration:

for ($i=0; $i<count($array); $i++) { // calls count() on each iteration
}

// Better
for ($i=0, $c=count($array); $i<$c; $i++) { // calls count() just once
}
Loading history...
370
                    if ($i != 0) {
371
                        $args .= ', ';
372
                    }
373
374
                    if (isset($modes_arr[$i])) {
375
                        switch ($modes_arr[$i]) {
376
                            case 'i':$args .= ' IN ';
377
                                break;
378
                            case 'o':$args .= ' OUT ';
379
                                break;
380
                            case 'b':$args .= ' INOUT ';
381
                                break;
382
                            case 'v':$args .= ' VARIADIC ';
383
                                break;
384
                            case 't':$args .= ' TABLE ';
385
                                break;
386
                        }
387
                    }
388
                    if (isset($names_arr[$i]) && $names_arr[$i] != '') {
389
                        $data->fieldClean($names_arr[$i]);
390
                        $args .= '"' . $names_arr[$i] . '" ';
391
                    }
392
                    $args .= $args_arr[$i];
393
                }
394
            } else {
395
                $args = $fndata->fields['proarguments'];
396
            }
397
398
            $func_full = $fndata->fields['proname'] . '(' . $fndata->fields['proarguments'] . ')';
0 ignored issues
show
Unused Code introduced by
The assignment to $func_full is dead and can be removed.
Loading history...
399
            echo '<form action="' . SUBFOLDER . "/src/views/functions.php\" method=\"post\">\n";
400
            echo "<table style=\"width: 90%\">\n";
401
            echo "<tr>\n";
402
            echo "<th class=\"data required\">{$lang['strschema']}</th>\n";
403
            echo "<th class=\"data required\">{$lang['strfunction']}</th>\n";
404
            echo "<th class=\"data\">{$lang['strarguments']}</th>\n";
405
            echo "<th class=\"data required\">{$lang['strreturns']}</th>\n";
406
            echo "<th class=\"data required\">{$lang['strproglanguage']}</th>\n";
407
            echo "</tr>\n";
408
409
            echo "<tr>\n";
410
            echo '<td class="data1">';
411
            echo '<input type="hidden" name="original_schema" value="', htmlspecialchars($fndata->fields['proschema']), "\" />\n";
412
            if ($data->hasFunctionAlterSchema()) {
413
                $schemas = $data->getSchemas();
414
                echo '<select name="formFuncSchema">';
415
                while (!$schemas->EOF) {
416
                    $schema = $schemas->fields['nspname'];
417
                    echo '<option value="', htmlspecialchars($schema), '"',
418
                    ($schema == $_POST['formFuncSchema']) ? ' selected="selected"' : '', '>', htmlspecialchars($schema), "</option>\n";
419
                    $schemas->moveNext();
420
                }
421
                echo "</select>\n";
422
            } else {
423
                echo $fndata->fields['proschema'];
424
            }
425
426
            echo "</td>\n";
427
            echo '<td class="data1">';
428
            echo '<input type="hidden" name="original_function" value="', htmlspecialchars($fndata->fields['proname']), "\" />\n";
429
            echo "<input name=\"formFunction\" style=\"width: 100%\" maxlength=\"{$data->_maxNameLen}\" value=\"", htmlspecialchars($_POST['formFunction']), '" />';
430
            echo "</td>\n";
431
432
            echo '<td class="data1">', $misc->printVal($args), "\n";
433
            echo '<input type="hidden" name="original_arguments" value="', htmlspecialchars($args), "\" />\n";
434
            echo "</td>\n";
435
436
            echo '<td class="data1">';
437
            if ($fndata->fields['proretset']) {
438
                echo 'setof ';
439
            }
440
441
            echo $misc->printVal($fndata->fields['proresult']), "\n";
442
            echo '<input type="hidden" name="original_returns" value="', htmlspecialchars($fndata->fields['proresult']), "\" />\n";
443
            if ($fndata->fields['proretset']) {
444
                echo "<input type=\"hidden\" name=\"original_setof\" value=\"yes\" />\n";
445
            }
446
447
            echo "</td>\n";
448
449
            echo '<td class="data1">', $misc->printVal($fndata->fields['prolanguage']), "\n";
450
            echo '<input type="hidden" name="original_lang" value="', htmlspecialchars($fndata->fields['prolanguage']), "\" />\n";
451
            echo "</td>\n";
452
            echo "</tr>\n";
453
454
            $fnlang = strtolower($fndata->fields['prolanguage']);
455 View Code Duplication
            if ($fnlang == 'c') {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
456
                echo "<tr><th class=\"data required\" colspan=\"2\">{$lang['strobjectfile']}</th>\n";
457
                echo "<th class=\"data\" colspan=\"2\">{$lang['strlinksymbol']}</th></tr>\n";
458
                echo '<tr><td class="data1" colspan="2"><input type="text" name="formObjectFile" style="width:100%" value="',
459
                htmlspecialchars($_POST['formObjectFile']), "\" /></td>\n";
460
                echo '<td class="data1" colspan="2"><input type="text" name="formLinkSymbol" style="width:100%" value="',
461
                htmlspecialchars($_POST['formLinkSymbol']), "\" /></td></tr>\n";
462
            } elseif ($fnlang == 'internal') {
463
                echo "<tr><th class=\"data\" colspan=\"5\">{$lang['strlinksymbol']}</th></tr>\n";
464
                echo '<tr><td class="data1" colspan="5"><input type="text" name="formLinkSymbol" style="width:100%" value="',
465
                htmlspecialchars($_POST['formLinkSymbol']), "\" /></td></tr>\n";
466
            } else {
467
                echo "<tr><th class=\"data required\" colspan=\"5\">{$lang['strdefinition']}</th></tr>\n";
468
                echo '<tr><td class="data1" colspan="5"><textarea style="width:100%;" rows="20" cols="50" name="formDefinition">',
469
                htmlspecialchars($_POST['formDefinition']), "</textarea></td></tr>\n";
470
            }
471
472
            // Display function comment
473
            echo "<tr><th class=\"data\" colspan=\"5\">{$lang['strcomment']}</th></tr>\n";
474
            echo '<tr><td class="data1" colspan="5"><textarea style="width:100%;" name="formComment" rows="3" cols="50">',
475
            htmlspecialchars($_POST['formComment']), "</textarea></td></tr>\n";
476
477
            // Display function cost options
478
            if ($data->hasFunctionCosting()) {
479
                echo "<tr><th class=\"data required\" colspan=\"5\">{$lang['strfunctioncosting']}</th></tr>\n";
480
                echo "<td class=\"data1\" colspan=\"2\">{$lang['strexecutioncost']}: <input name=\"formCost\" size=\"16\" value=\"" .
481
                htmlspecialchars($_POST['formCost']) . '" /></td>';
482
                echo "<td class=\"data1\" colspan=\"2\">{$lang['strresultrows']}: <input name=\"formRows\" size=\"16\" value=\"",
483
                htmlspecialchars($_POST['formRows']), '"', (!$fndata->fields['proretset']) ? 'disabled' : '', '/></td>';
484
            }
485
486
            // Display function properties
487 View Code Duplication
            if (is_array($data->funcprops) && sizeof($data->funcprops) > 0) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
488
                echo "<tr><th class=\"data\" colspan=\"5\">{$lang['strproperties']}</th></tr>\n";
489
                echo "<tr><td class=\"data1\" colspan=\"5\">\n";
490
                $i = 0;
491
                foreach ($data->funcprops as $k => $v) {
492
                    echo "<select name=\"formProperties[{$i}]\">\n";
493
                    foreach ($v as $p) {
494
                        echo '<option value="', htmlspecialchars($p), '"',
495
                        ($p == $_POST['formProperties'][$i]) ? ' selected="selected"' : '',
496
                        '>', $misc->printVal($p), "</option>\n";
497
                    }
498
                    echo "</select><br />\n";
499
                    $i++;
500
                }
501
                echo "</td></tr>\n";
502
            }
503
504
            // function owner
505 View Code Duplication
            if ($data->hasFunctionAlterOwner()) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
506
                $users = $data->getUsers();
507
                echo "<tr><td class=\"data1\" colspan=\"5\">{$lang['strowner']}: <select name=\"formFuncOwn\">";
508
                while (!$users->EOF) {
509
                    $uname = $users->fields['usename'];
510
                    echo '<option value="', htmlspecialchars($uname), '"',
511
                    ($uname == $_POST['formFuncOwn']) ? ' selected="selected"' : '', '>', htmlspecialchars($uname), "</option>\n";
512
                    $users->moveNext();
513
                }
514
                echo "</select>\n";
515
                echo '<input type="hidden" name="original_owner" value="', htmlspecialchars($fndata->fields['proowner']), "\" />\n";
516
                echo "</td></tr>\n";
517
            }
518
            echo "</table>\n";
519
            echo "<p><input type=\"hidden\" name=\"action\" value=\"save_edit\" />\n";
520
            echo '<input type="hidden" name="function" value="', htmlspecialchars($_REQUEST['function']), "\" />\n";
521
            echo '<input type="hidden" name="function_oid" value="', htmlspecialchars($_REQUEST['function_oid']), "\" />\n";
522
            echo $misc->form;
523
            echo "<input type=\"submit\" value=\"{$lang['stralter']}\" />\n";
524
            echo "<input type=\"submit\" name=\"cancel\" value=\"{$lang['strcancel']}\" /></p>\n";
525
            echo "</form>\n";
526
        } else {
527
            echo "<p>{$lang['strnodata']}</p>\n";
528
        }
529
    }
530
531
    /**
532
     * Show read only properties of a function
533
     */
534
    public function doProperties($msg = '')
0 ignored issues
show
Coding Style introduced by
doProperties uses the super-global variable $_REQUEST which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
535
    {
536
        $conf = $this->conf;
537
        $misc = $this->misc;
538
        $lang = $this->lang;
539
        $data = $misc->getDatabaseAccessor();
540
541
        $this->printTrail('function');
542
        $this->printTitle($lang['strproperties'], 'pg.function');
543
        $this->printMsg($msg);
544
545
        $funcdata = $data->getFunction($_REQUEST['function_oid']);
546
547
        if ($funcdata->recordCount() > 0) {
548
549
            // Deal with named parameters
550 View Code Duplication
            if ($data->hasNamedParams()) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
551
                if (isset($funcdata->fields['proallarguments'])) {
552
                    $args_arr = $data->phpArray($funcdata->fields['proallarguments']);
553
                } else {
554
                    $args_arr = explode(', ', $funcdata->fields['proarguments']);
555
                }
556
                $names_arr = $data->phpArray($funcdata->fields['proargnames']);
557
                $modes_arr = $data->phpArray($funcdata->fields['proargmodes']);
558
                $args      = '';
559
                $i         = 0;
0 ignored issues
show
Unused Code introduced by
The assignment to $i is dead and can be removed.
Loading history...
560
                for ($i = 0; $i < sizeof($args_arr); $i++) {
0 ignored issues
show
Performance Best Practice introduced by
It seems like you are calling the size function sizeof() as part of the test condition. You might want to compute the size beforehand, and not on each iteration.

If the size of the collection does not change during the iteration, it is generally a good practice to compute it beforehand, and not on each iteration:

for ($i=0; $i<count($array); $i++) { // calls count() on each iteration
}

// Better
for ($i=0, $c=count($array); $i<$c; $i++) { // calls count() just once
}
Loading history...
561
                    if ($i != 0) {
562
                        $args .= ', ';
563
                    }
564
565
                    if (isset($modes_arr[$i])) {
566
                        switch ($modes_arr[$i]) {
567
                            case 'i':
568
                                $args .= ' IN ';
569
                                break;
570
                            case 'o':
571
                                $args .= ' OUT ';
572
                                break;
573
                            case 'b':
574
                                $args .= ' INOUT ';
575
                                break;
576
                            case 'v':
577
                                $args .= ' VARIADIC ';
578
                                break;
579
                            case 't':
580
                                $args .= ' TABLE ';
581
                                break;
582
                        }
583
                    }
584
                    if (isset($names_arr[$i]) && $names_arr[$i] != '') {
585
                        $data->fieldClean($names_arr[$i]);
586
                        $args .= '"' . $names_arr[$i] . '" ';
587
                    }
588
                    $args .= $args_arr[$i];
589
                }
590
            } else {
591
                $args = $funcdata->fields['proarguments'];
592
            }
593
594
            // Show comment if any
595
            if ($funcdata->fields['procomment'] !== null) {
596
                echo '<p class="comment">', $misc->printVal($funcdata->fields['procomment']), "</p>\n";
597
            }
598
599
            $funcdata->fields['proretset'] = $data->phpBool($funcdata->fields['proretset']);
600
            $func_full                     = $funcdata->fields['proname'] . '(' . $funcdata->fields['proarguments'] . ')';
601
            echo "<table style=\"width: 90%\">\n";
602
            echo "<tr><th class=\"data\">{$lang['strfunction']}</th>\n";
603
            echo "<th class=\"data\">{$lang['strarguments']}</th>\n";
604
            echo "<th class=\"data\">{$lang['strreturns']}</th>\n";
605
            echo "<th class=\"data\">{$lang['strproglanguage']}</th></tr>\n";
606
            echo '<tr><td class="data1">', $misc->printVal($funcdata->fields['proname']), "</td>\n";
607
            echo '<td class="data1">', $misc->printVal($args), "</td>\n";
608
            echo '<td class="data1">';
609
            if ($funcdata->fields['proretset']) {
610
                echo 'setof ';
611
            }
612
613
            echo $misc->printVal($funcdata->fields['proresult']), "</td>\n";
614
            echo '<td class="data1">', $misc->printVal($funcdata->fields['prolanguage']), "</td></tr>\n";
615
616
            $fnlang = strtolower($funcdata->fields['prolanguage']);
617
            if ($fnlang == 'c') {
618
                echo "<tr><th class=\"data\" colspan=\"2\">{$lang['strobjectfile']}</th>\n";
619
                echo "<th class=\"data\" colspan=\"2\">{$lang['strlinksymbol']}</th></tr>\n";
620
                echo '<tr><td class="data1" colspan="2">', $misc->printVal($funcdata->fields['probin']), "</td>\n";
621
                echo '<td class="data1" colspan="2">', $misc->printVal($funcdata->fields['prosrc']), "</td></tr>\n";
622
            } elseif ($fnlang == 'internal') {
623
                echo "<tr><th class=\"data\" colspan=\"4\">{$lang['strlinksymbol']}</th></tr>\n";
624
                echo '<tr><td class="data1" colspan="4">', $misc->printVal($funcdata->fields['prosrc']), "</td></tr>\n";
625
            } else {
626
                $highlight = new \PHPPgAdmin\Highlight();
627
628
                echo "<tr><th class=\"data\" colspan=\"4\">{$lang['strdefinition']}</th></tr>\n";
629
                // Check to see if we have syntax highlighting for this language
630
                if (array_key_exists($fnlang, $data->langmap)) {
631
                    $temp = $highlight->syntax_highlight(htmlspecialchars($funcdata->fields['prosrc']), $data->langmap[$fnlang]);
632
                    $tag  = 'prenoescape';
633
                } else {
634
                    $temp = $funcdata->fields['prosrc'];
635
                    $tag  = 'pre';
636
                }
637
                echo '<tr><td class="data1" colspan="4">', $misc->printVal($temp, $tag, ['lineno' => true, 'class' => 'data1']), "</td></tr>\n";
638
            }
639
640
            // Display function cost options
641
            if ($data->hasFunctionCosting()) {
642
                echo "<tr><th class=\"data required\" colspan=\"4\">{$lang['strfunctioncosting']}</th></tr>\n";
643
                echo "<td class=\"data1\" colspan=\"2\">{$lang['strexecutioncost']}: ", $misc->printVal($funcdata->fields['procost']), ' </td>';
644
                echo "<td class=\"data1\" colspan=\"2\">{$lang['strresultrows']}: ", $misc->printVal($funcdata->fields['prorows']), ' </td>';
645
            }
646
647
            // Show flags
648
            if (is_array($data->funcprops) && sizeof($data->funcprops) > 0) {
649
                // Fetch an array of the function properties
650
                $funcprops = $data->getFunctionProperties($funcdata->fields);
651
                echo "<tr><th class=\"data\" colspan=\"4\">{$lang['strproperties']}</th></tr>\n";
652
                echo "<tr><td class=\"data1\" colspan=\"4\">\n";
653
                foreach ($funcprops as $v) {
654
                    echo $misc->printVal($v), "<br />\n";
655
                }
656
                echo "</td></tr>\n";
657
            }
658
659
            echo "<tr><td class=\"data1\" colspan=\"5\">{$lang['strowner']}: ", htmlspecialchars($funcdata->fields['proowner']), "\n";
660
            echo "</td></tr>\n";
661
            echo "</table>\n";
662
        } else {
663
            echo "<p>{$lang['strnodata']}</p>\n";
664
        }
665
666
        $navlinks = [
667
            'showall' => [
668
                'attr'    => [
669
                    'href' => [
670
                        'url'     => 'functions.php',
671
                        'urlvars' => [
672
                            'server'   => $_REQUEST['server'],
673
                            'database' => $_REQUEST['database'],
674
                            'schema'   => $_REQUEST['schema'],
675
                        ],
676
                    ],
677
                ],
678
                'content' => $lang['strshowallfunctions'],
679
            ],
680
            'alter'   => [
681
                'attr'    => [
682
                    'href' => [
683
                        'url'     => 'functions.php',
684
                        'urlvars' => [
685
                            'action'       => 'edit',
686
                            'server'       => $_REQUEST['server'],
687
                            'database'     => $_REQUEST['database'],
688
                            'schema'       => $_REQUEST['schema'],
689
                            'function'     => $_REQUEST['function'],
690
                            'function_oid' => $_REQUEST['function_oid'],
691
                        ],
692
                    ],
693
                ],
694
                'content' => $lang['stralter'],
695
            ],
696
            'drop'    => [
697
                'attr'    => [
698
                    'href' => [
699
                        'url'     => 'functions.php',
700
                        'urlvars' => [
701
                            'action'       => 'confirm_drop',
702
                            'server'       => $_REQUEST['server'],
703
                            'database'     => $_REQUEST['database'],
704
                            'schema'       => $_REQUEST['schema'],
705
                            'function'     => $func_full,
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $func_full does not seem to be defined for all execution paths leading up to this point.
Loading history...
706
                            'function_oid' => $_REQUEST['function_oid'],
707
                        ],
708
                    ],
709
                ],
710
                'content' => $lang['strdrop'],
711
            ],
712
        ];
713
714
        $this->printNavLinks($navlinks, 'functions-properties', get_defined_vars());
715
    }
716
717
    /**
718
     * Show confirmation of drop and perform actual drop
719
     */
720
    public function doDrop($confirm)
0 ignored issues
show
Coding Style introduced by
doDrop uses the super-global variable $_REQUEST which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
Coding Style introduced by
doDrop uses the super-global variable $_POST which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
721
    {
722
        $conf = $this->conf;
0 ignored issues
show
Unused Code introduced by
The assignment to $conf is dead and can be removed.
Loading history...
723
        $misc = $this->misc;
724
        $lang = $this->lang;
725
        $data = $misc->getDatabaseAccessor();
726
727
        if (empty($_REQUEST['function']) && empty($_REQUEST['ma'])) {
728
            $this->doDefault($lang['strspecifyfunctiontodrop']);
729
            exit();
0 ignored issues
show
Coding Style Compatibility introduced by
The method doDrop() contains an exit expression.

An exit expression should only be used in rare cases. For example, if you write a short command line script.

In most cases however, using an exit expression makes the code untestable and often causes incompatibilities with other libraries. Thus, unless you are absolutely sure it is required here, we recommend to refactor your code to avoid its usage.

Loading history...
730
        }
731
732
        if ($confirm) {
733
            $this->printTrail('schema');
734
            $this->printTitle($lang['strdrop'], 'pg.function.drop');
735
736
            echo '<form action="' . SUBFOLDER . "/src/views/functions.php\" method=\"post\">\n";
737
738
            //If multi drop
739
            if (isset($_REQUEST['ma'])) {
740
                foreach ($_REQUEST['ma'] as $v) {
741
                    $a = unserialize(htmlspecialchars_decode($v, ENT_QUOTES));
0 ignored issues
show
Security introduced by
htmlspecialchars_decode(...\Controller\ENT_QUOTES) can contain request data and is used in unserialized context(s) leading to a potential security vulnerability.

1 path for user data to reach this point

  1. Read from $_REQUEST, and $_REQUEST['ma'] is assigned to $v
    in src/controllers/FunctionsController.php on line 740
  2. Data is passed through htmlspecialchars_decode()
    in src/controllers/FunctionsController.php on line 741

Preventing Object Injection Attacks

If you pass raw user-data to unserialize() for example, this can be used to create an object of any class that is available in your local filesystem. For an attacker, classes that have magic methods like __destruct or __wakeup are particularly interesting in such a case, as they can be exploited very easily.

We recommend to not pass user data to such a function. In case of unserialize, better use JSON to transfer data.

General Strategies to prevent injection

In general, it is advisable to prevent any user-data to reach this point. This can be done by white-listing certain values:

if ( ! in_array($value, array('this-is-allowed', 'and-this-too'), true)) {
    throw new \InvalidArgumentException('This input is not allowed.');
}

For numeric data, we recommend to explicitly cast the data:

$sanitized = (integer) $tainted;
Loading history...
742
                    echo '<p>', sprintf($lang['strconfdropfunction'], $misc->printVal($a['function'])), "</p>\n";
743
                    echo '<input type="hidden" name="function[]" value="', htmlspecialchars($a['function']), "\" />\n";
744
                    echo '<input type="hidden" name="function_oid[]" value="', htmlspecialchars($a['function_oid']), "\" />\n";
745
                }
746
            } else {
747
                echo '<p>', sprintf($lang['strconfdropfunction'], $misc->printVal($_REQUEST['function'])), "</p>\n";
748
                echo '<input type="hidden" name="function" value="', htmlspecialchars($_REQUEST['function']), "\" />\n";
749
                echo '<input type="hidden" name="function_oid" value="', htmlspecialchars($_REQUEST['function_oid']), "\" />\n";
750
            }
751
752
            echo "<input type=\"hidden\" name=\"action\" value=\"drop\" />\n";
753
754
            echo $misc->form;
755
            echo "<p><input type=\"checkbox\" id=\"cascade\" name=\"cascade\" /><label for=\"cascade\">{$lang['strcascade']}</label></p>\n";
756
            echo "<input type=\"submit\" name=\"drop\" value=\"{$lang['strdrop']}\" />\n";
757
            echo "<input type=\"submit\" name=\"cancel\" value=\"{$lang['strcancel']}\" />\n";
758
            echo "</form>\n";
759
        } else {
760
            if (is_array($_POST['function_oid'])) {
761
                $msg    = '';
762
                $status = $data->beginTransaction();
763
                if ($status == 0) {
764
                    foreach ($_POST['function_oid'] as $k => $s) {
765
                        $status = $data->dropFunction($s, isset($_POST['cascade']));
766
                        if ($status == 0) {
767
                            $msg .= sprintf('%s: %s<br />', htmlentities($_POST['function'][$k], ENT_QUOTES, 'UTF-8'), $lang['strfunctiondropped']);
768
                        } else {
769
                            $data->endTransaction();
770
                            $this->doDefault(sprintf('%s%s: %s<br />', $msg, htmlentities($_POST['function'][$k], ENT_QUOTES, 'UTF-8'), $lang['strfunctiondroppedbad']));
771
                            return;
772
                        }
773
                    }
774
                }
775
                if ($data->endTransaction() == 0) {
776
                    // Everything went fine, back to the Default page....
777
                    $this->misc->setReloadBrowser(true);
778
                    $this->doDefault($msg);
779
                } else {
780
                    $this->doDefault($lang['strfunctiondroppedbad']);
781
                }
782
            } else {
783
                $status = $data->dropFunction($_POST['function_oid'], isset($_POST['cascade']));
784
                if ($status == 0) {
785
                    $this->misc->setReloadBrowser(true);
786
                    $this->doDefault($lang['strfunctiondropped']);
787
                } else {
788
                    $this->doDefault($lang['strfunctiondroppedbad']);
789
                }
790
            }
791
        }
792
    }
793
794
    /**
795
     * Displays a screen where they can enter a new function
796
     */
797
    public function doCreate($msg = '', $szJS = '')
0 ignored issues
show
Coding Style introduced by
doCreate uses the super-global variable $_POST which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
Coding Style introduced by
doCreate uses the super-global variable $_REQUEST which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
798
    {
799
        $conf = $this->conf;
800
        $misc = $this->misc;
801
        $lang = $this->lang;
802
        $data = $misc->getDatabaseAccessor();
803
804
        $this->printTrail('schema');
805
        if (!isset($_POST['formFunction'])) {
806
            $_POST['formFunction'] = '';
807
        }
808
809
        if (!isset($_POST['formArguments'])) {
810
            $_POST['formArguments'] = '';
811
        }
812
813
        if (!isset($_POST['formReturns'])) {
814
            $_POST['formReturns'] = '';
815
        }
816
817
        if (!isset($_POST['formLanguage'])) {
818
            $_POST['formLanguage'] = isset($_REQUEST['language']) ? $_REQUEST['language'] : 'sql';
819
        }
820
821
        if (!isset($_POST['formDefinition'])) {
822
            $_POST['formDefinition'] = '';
823
        }
824
825
        if (!isset($_POST['formObjectFile'])) {
826
            $_POST['formObjectFile'] = '';
827
        }
828
829
        if (!isset($_POST['formLinkSymbol'])) {
830
            $_POST['formLinkSymbol'] = '';
831
        }
832
833
        if (!isset($_POST['formProperties'])) {
834
            $_POST['formProperties'] = $data->defaultprops;
835
        }
836
837
        if (!isset($_POST['formSetOf'])) {
838
            $_POST['formSetOf'] = '';
839
        }
840
841
        if (!isset($_POST['formArray'])) {
842
            $_POST['formArray'] = '';
843
        }
844
845
        if (!isset($_POST['formCost'])) {
846
            $_POST['formCost'] = '';
847
        }
848
849
        if (!isset($_POST['formRows'])) {
850
            $_POST['formRows'] = '';
851
        }
852
853
        if (!isset($_POST['formComment'])) {
854
            $_POST['formComment'] = '';
855
        }
856
857
        $types  = $data->getTypes(true, true, true);
858
        $langs  = $data->getLanguages(true);
859
        $fnlang = strtolower($_POST['formLanguage']);
860
861
        switch ($fnlang) {
862
            case 'c':
863
                $this->printTitle($lang['strcreatecfunction'], 'pg.function.create.c');
864
                break;
865
            case 'internal':
866
                $this->printTitle($lang['strcreateinternalfunction'], 'pg.function.create.internal');
867
                break;
868
            default:
869
                $this->printTitle($lang['strcreateplfunction'], 'pg.function.create.pl');
870
                break;
871
        }
872
        $this->printMsg($msg);
873
874
        // Create string for return type list
875
        $szTypes = '';
876
        while (!$types->EOF) {
877
            $szSelected = '';
878
            if ($types->fields['typname'] == $_POST['formReturns']) {
879
                $szSelected = ' selected="selected"';
880
            }
881
            /* this variable is include in the JS code bellow, so we need to ENT_QUOTES */
882
            $szTypes .= '<option value="' . htmlspecialchars($types->fields['typname'], ENT_QUOTES) . "\"{$szSelected}>";
883
            $szTypes .= htmlspecialchars($types->fields['typname'], ENT_QUOTES) . '</option>';
884
            $types->moveNext();
885
        }
886
887
        $szFunctionName = "<td class=\"data1\"><input name=\"formFunction\" size=\"16\" maxlength=\"{$data->_maxNameLen}\" value=\"" .
888
        htmlspecialchars($_POST['formFunction']) . '" /></td>';
889
890
        $szArguments = '<td class="data1"><input name="formArguments" style="width:100%;" size="16" value="' .
1 ignored issue
show
Unused Code introduced by
The assignment to $szArguments is dead and can be removed.
Loading history...
891
        htmlspecialchars($_POST['formArguments']) . '" /></td>';
892
893
        $szSetOfSelected    = '';
894
        $szNotSetOfSelected = '';
895
        if ($_POST['formSetOf'] == '') {
896
            $szNotSetOfSelected = ' selected="selected"';
897
        } elseif ($_POST['formSetOf'] == 'SETOF') {
898
            $szSetOfSelected = ' selected="selected"';
899
        }
900
        $szReturns = '<td class="data1" colspan="2">';
901
        $szReturns .= '<select name="formSetOf">';
902
        $szReturns .= "<option value=\"\"{$szNotSetOfSelected}></option>";
903
        $szReturns .= "<option value=\"SETOF\"{$szSetOfSelected}>SETOF</option>";
904
        $szReturns .= '</select>';
905
906
        $szReturns .= '<select name="formReturns">' . $szTypes . '</select>';
907
908
        // Create string array type selector
909
910
        $szArraySelected    = '';
911
        $szNotArraySelected = '';
912
        if ($_POST['formArray'] == '') {
913
            $szNotArraySelected = ' selected="selected"';
914
        } elseif ($_POST['formArray'] == '[]') {
915
            $szArraySelected = ' selected="selected"';
916
        }
917
918
        $szReturns .= '<select name="formArray">';
919
        $szReturns .= "<option value=\"\"{$szNotArraySelected}></option>";
920
        $szReturns .= "<option value=\"[]\"{$szArraySelected}>[ ]</option>";
921
        $szReturns .= "</select>\n</td>";
922
923
        // Create string for language
924
        $szLanguage = '<td class="data1">';
925
        if ($fnlang == 'c' || $fnlang == 'internal') {
926
            $szLanguage .= $_POST['formLanguage'] . "\n";
927
            $szLanguage .= "<input type=\"hidden\" name=\"formLanguage\" value=\"{$_POST['formLanguage']}\" />\n";
928
        } else {
929
            $szLanguage .= "<select name=\"formLanguage\">\n";
930
            while (!$langs->EOF) {
931
                $szSelected = '';
932
                if ($langs->fields['lanname'] == $_POST['formLanguage']) {
933
                    $szSelected = ' selected="selected"';
934
                }
935
                if (strtolower($langs->fields['lanname']) != 'c' && strtolower($langs->fields['lanname']) != 'internal') {
936
                    $szLanguage .= '<option value="' . htmlspecialchars($langs->fields['lanname']) . "\"{$szSelected}>\n" .
937
                    $misc->printVal($langs->fields['lanname']) . '</option>';
938
                }
939
940
                $langs->moveNext();
941
            }
942
            $szLanguage .= "</select>\n";
943
        }
944
945
        $szLanguage .= '</td>';
946
        $szJSArguments = "<tr><th class=\"data\" colspan=\"7\">{$lang['strarguments']}</th></tr>";
947
        $arrayModes    = ['IN', 'OUT', 'INOUT'];
948
        $szModes       = '<select name="formArgModes[]" style="width:100%;">';
949
        foreach ($arrayModes as $pV) {
950
            $szModes .= "<option value=\"{$pV}\">{$pV}</option>";
951
        }
952
        $szModes .= '</select>';
953
        $szArgReturns = '<select name="formArgArray[]">';
954
        $szArgReturns .= '<option value=""></option>';
955
        $szArgReturns .= '<option value="[]">[]</option>';
956
        $szArgReturns .= '</select>';
957
        if (!empty($conf['theme'])) {
958
            $szImgPath = "images/themes/{$conf['theme']}";
959
        } else {
960
            $szImgPath = 'images/themes/default';
961
        }
962
        if (empty($msg)) {
963
            $szJSTRArg = "<script type=\"text/javascript\" >addArg();</script>\n";
964
        } else {
965
            $szJSTRArg = '';
966
        }
967
        $szJSAddTR = "<tr id=\"parent_add_tr\" onclick=\"addArg();\" onmouseover=\"this.style.cursor='pointer'\">\n<td style=\"text-align: right\" colspan=\"6\" class=\"data3\"><table><tr><td class=\"data3\"><img src=\"{$szImgPath}/AddArguments.png\" alt=\"Add Argument\" /></td><td class=\"data3\"><span style=\"font-size: 8pt\">{$lang['strargadd']}</span></td></tr></table></td>\n</tr>\n";
968
969
        echo '<script src="' . SUBFOLDER . "/js/functions.js\" type=\"text/javascript\"></script>
970
		<script type=\"text/javascript\">
971
			//<![CDATA[
972
			var g_types_select = '<select name=\"formArgType[]\">{$szTypes}</select>{$szArgReturns}';
973
			var g_modes_select = '{$szModes}';
974
			var g_name = '';
975
			var g_lang_strargremove = '", htmlspecialchars($lang['strargremove'], ENT_QUOTES), "';
976
			var g_lang_strargnoargs = '", htmlspecialchars($lang['strargnoargs'], ENT_QUOTES), "';
977
			var g_lang_strargenableargs = '", htmlspecialchars($lang['strargenableargs'], ENT_QUOTES), "';
978
			var g_lang_strargnorowabove = '", htmlspecialchars($lang['strargnorowabove'], ENT_QUOTES), "';
979
			var g_lang_strargnorowbelow = '", htmlspecialchars($lang['strargnorowbelow'], ENT_QUOTES), "';
980
			var g_lang_strargremoveconfirm = '", htmlspecialchars($lang['strargremoveconfirm'], ENT_QUOTES), "';
981
			var g_lang_strargraise = '", htmlspecialchars($lang['strargraise'], ENT_QUOTES), "';
982
			var g_lang_strarglower = '", htmlspecialchars($lang['strarglower'], ENT_QUOTES), "';
983
			//]]>
984
		</script>
985
		";
986
        echo '<form action="' . SUBFOLDER . "/src/views//views/functions.php\" method=\"post\">\n";
987
        echo "<table><tbody id=\"args_table\">\n";
988
        echo "<tr><th class=\"data required\">{$lang['strname']}</th>\n";
989
        echo "<th class=\"data required\" colspan=\"2\">{$lang['strreturns']}</th>\n";
990
        echo "<th class=\"data required\">{$lang['strproglanguage']}</th></tr>\n";
991
        echo "<tr>\n";
992
        echo "{$szFunctionName}\n";
993
        echo "{$szReturns}\n";
994
        echo "{$szLanguage}\n";
995
        echo "</tr>\n";
996
        echo "{$szJSArguments}\n";
997
        echo "<tr>\n";
998
        echo "<th class=\"data required\">{$lang['strargmode']}</th>\n";
999
        echo "<th class=\"data required\">{$lang['strname']}</th>\n";
1000
        echo "<th class=\"data required\" colspan=\"2\">{$lang['strargtype']}</th>\n";
1001
        echo "</tr>\n";
1002
        echo "{$szJSAddTR}\n";
1003
1004 View Code Duplication
        if ($fnlang == 'c') {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1005
            echo "<tr><th class=\"data required\" colspan=\"2\">{$lang['strobjectfile']}</th>\n";
1006
            echo "<th class=\"data\" colspan=\"2\">{$lang['strlinksymbol']}</th></tr>\n";
1007
            echo '<tr><td class="data1" colspan="2"><input type="text" name="formObjectFile" style="width:100%" value="',
1008
            htmlspecialchars($_POST['formObjectFile']), "\" /></td>\n";
1009
            echo '<td class="data1" colspan="2"><input type="text" name="formLinkSymbol" style="width:100%" value="',
1010
            htmlspecialchars($_POST['formLinkSymbol']), "\" /></td></tr>\n";
1011
        } elseif ($fnlang == 'internal') {
1012
            echo "<tr><th class=\"data\" colspan=\"4\">{$lang['strlinksymbol']}</th></tr>\n";
1013
            echo '<tr><td class="data1" colspan="4"><input type="text" name="formLinkSymbol" style="width:100%" value="',
1014
            htmlspecialchars($_POST['formLinkSymbol']), "\" /></td></tr>\n";
1015
        } else {
1016
            echo "<tr><th class=\"data required\" colspan=\"4\">{$lang['strdefinition']}</th></tr>\n";
1017
            echo '<tr><td class="data1" colspan="4"><textarea style="width:100%;" rows="20" cols="50" name="formDefinition">',
1018
            htmlspecialchars($_POST['formDefinition']), "</textarea></td></tr>\n";
1019
        }
1020
1021
        // Display function comment
1022
        echo "<tr><th class=\"data\" colspan=\"4\">{$lang['strcomment']}</th></tr>\n";
1023
        echo '<tr><td class="data1" colspan="4"><textarea style="width:100%;" name="formComment" rows="3" cols="50">',
1024
        htmlspecialchars($_POST['formComment']), "</textarea></td></tr>\n";
1025
1026
        // Display function cost options
1027
        if ($data->hasFunctionCosting()) {
1028
            echo "<tr><th class=\"data required\" colspan=\"4\">{$lang['strfunctioncosting']}</th></tr>\n";
1029
            echo "<td class=\"data1\" colspan=\"2\">{$lang['strexecutioncost']}: <input name=\"formCost\" size=\"16\" value=\"" .
1030
            htmlspecialchars($_POST['formCost']) . '" /></td>';
1031
            echo "<td class=\"data1\" colspan=\"2\">{$lang['strresultrows']}: <input name=\"formRows\" size=\"16\" value=\"" .
1032
            htmlspecialchars($_POST['formRows']) . '" /></td>';
1033
        }
1034
1035
        // Display function properties
1036 View Code Duplication
        if (is_array($data->funcprops) && sizeof($data->funcprops) > 0) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1037
            echo "<tr><th class=\"data required\" colspan=\"4\">{$lang['strproperties']}</th></tr>\n";
1038
            echo "<tr><td class=\"data1\" colspan=\"4\">\n";
1039
            $i = 0;
1040
            foreach ($data->funcprops as $k => $v) {
1041
                echo "<select name=\"formProperties[{$i}]\">\n";
1042
                foreach ($v as $p) {
1043
                    echo '<option value="', htmlspecialchars($p), '"',
1044
                    ($p == $_POST['formProperties'][$i]) ? ' selected="selected"' : '',
1045
                    '>', $misc->printVal($p), "</option>\n";
1046
                }
1047
                echo "</select><br />\n";
1048
                $i++;
1049
            }
1050
            echo "</td></tr>\n";
1051
        }
1052
        echo "</tbody></table>\n";
1053
        echo $szJSTRArg;
1054
        echo "<p><input type=\"hidden\" name=\"action\" value=\"save_create\" />\n";
1055
        echo $misc->form;
1056
        echo "<input type=\"submit\" value=\"{$lang['strcreate']}\" />\n";
1057
        echo "<input type=\"submit\" name=\"cancel\" value=\"{$lang['strcancel']}\" /></p>\n";
1058
        echo "</form>\n";
1059
        echo $szJS;
1060
    }
1061
1062
    /**
1063
     * Actually creates the new function in the database
1064
     */
1065
    public function doSaveCreate()
0 ignored issues
show
Coding Style introduced by
doSaveCreate uses the super-global variable $_POST which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
1066
    {
1067
        $conf = $this->conf;
0 ignored issues
show
Unused Code introduced by
The assignment to $conf is dead and can be removed.
Loading history...
1068
        $misc = $this->misc;
1069
        $lang = $this->lang;
1070
        $data = $misc->getDatabaseAccessor();
1071
1072
        $fnlang = strtolower($_POST['formLanguage']);
1073
1074 View Code Duplication
        if ($fnlang == 'c') {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1075
            $def = [$_POST['formObjectFile'], $_POST['formLinkSymbol']];
1076
        } elseif ($fnlang == 'internal') {
1077
            $def = $_POST['formLinkSymbol'];
1078
        } else {
1079
            $def = $_POST['formDefinition'];
1080
        }
1081
1082
        $szJS = '';
1083
1084
        echo '<script src="' . SUBFOLDER . '/js/functions.js" type="text/javascript"></script>';
1085
        echo '<script type="text/javascript">' . $this->buildJSData() . '</script>';
1086
        if (!empty($_POST['formArgName'])) {
1087
            $szJS = $this->buildJSRows($this->buildFunctionArguments($_POST));
1088
        } else {
1089
            $szJS = '<script type="text/javascript" src="' . SUBFOLDER . '/js/functions.js">noArgsRebuild(addArg());</script>';
1090
        }
1091
1092
        $cost = (isset($_POST['formCost'])) ? $_POST['formCost'] : null;
1093 View Code Duplication
        if ($cost == '' || !is_numeric($cost) || $cost != (int) $cost || $cost < 0) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1094
            $cost = null;
1095
        }
1096
1097
        $rows = (isset($_POST['formRows'])) ? $_POST['formRows'] : null;
1098 View Code Duplication
        if ($rows == '' || !is_numeric($rows) || $rows != (int) $rows) {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1099
            $rows = null;
1100
        }
1101
1102
        // Check that they've given a name and a definition
1103
        if ($_POST['formFunction'] == '') {
1104
            $this->doCreate($lang['strfunctionneedsname'], $szJS);
1105
        } elseif ($fnlang != 'internal' && !$def) {
1106
            $this->doCreate($lang['strfunctionneedsdef'], $szJS);
1107
        } else {
1108
            // Append array symbol to type if chosen
1109
            $status = $data->createFunction($_POST['formFunction'], empty($_POST['nojs']) ? $this->buildFunctionArguments($_POST) : $_POST['formArguments'],
1110
                $_POST['formReturns'] . $_POST['formArray'], $def, $_POST['formLanguage'],
1111
                $_POST['formProperties'], $_POST['formSetOf'] == 'SETOF',
1112
                $cost, $rows, $_POST['formComment'], false);
1113
            if ($status == 0) {
1114
                $this->doDefault($lang['strfunctioncreated']);
1115
            } else {
1116
                $this->doCreate($lang['strfunctioncreatedbad'], $szJS);
1117
            }
1118
        }
1119
    }
1120
1121
    /**
1122
     * Build out the function arguments string
1123
     */
1124
    private function buildFunctionArguments($arrayVars)
0 ignored issues
show
Coding Style introduced by
buildFunctionArguments uses the super-global variable $_POST which is generally not recommended.

Instead of super-globals, we recommend to explicitly inject the dependencies of your class. This makes your code less dependent on global state and it becomes generally more testable:

// Bad
class Router
{
    public function generate($path)
    {
        return $_SERVER['HOST'].$path;
    }
}

// Better
class Router
{
    private $host;

    public function __construct($host)
    {
        $this->host = $host;
    }

    public function generate($path)
    {
        return $this->host.$path;
    }
}

class Controller
{
    public function myAction(Request $request)
    {
        // Instead of
        $page = isset($_GET['page']) ? intval($_GET['page']) : 1;

        // Better (assuming you use the Symfony2 request)
        $page = $request->query->get('page', 1);
    }
}
Loading history...
1125
    {
1126
        if (isset($_POST['formArgName'])) {
1127
            $arrayArgs = [];
1128
            foreach ($arrayVars['formArgName'] as $pK => $pV) {
1129
                $arrayArgs[] = $arrayVars['formArgModes'][$pK] . ' ' . trim($pV) . ' ' . trim($arrayVars['formArgType'][$pK]) . $arrayVars['formArgArray'][$pK];
1130
            }
1131
            return implode(',', $arrayArgs);
1132
        }
1133
        return '';
1134
    }
1135
1136
    /**
1137
     * Build out JS to re-create table rows for arguments
1138
     */
1139
    private function buildJSRows($szArgs)
1140
    {
1141
        $arrayModes      = ['IN', 'OUT', 'INOUT'];
1142
        $arrayArgs       = explode(',', $szArgs);
1143
        $arrayProperArgs = [];
1144
        $nC              = 0;
1145
        $szReturn        = '';
1146
        foreach ($arrayArgs as $pV) {
1147
            $arrayWords = explode(' ', $pV);
1148
            if (in_array($arrayWords[0], $arrayModes) === true) {
1149
                $szMode = $arrayWords[0];
1150
                array_shift($arrayWords);
1151
            }
1152
            $szArgName = array_shift($arrayWords);
1153
            if (strpos($arrayWords[count($arrayWords) - 1], '[]') === false) {
1154
                $szArgType   = implode(' ', $arrayWords);
1155
                $bArgIsArray = 'false';
1156
            } else {
1157
                $szArgType   = str_replace('[]', '', implode(' ', $arrayWords));
1158
                $bArgIsArray = 'true';
1159
            }
1160
            $arrayProperArgs[] = [$szMode, $szArgName, $szArgType, $bArgIsArray];
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $szMode does not seem to be defined for all execution paths leading up to this point.
Loading history...
1161
            $szReturn .= "<script type=\"text/javascript\">RebuildArgTR('{$szMode}','{$szArgName}','{$szArgType}',new Boolean({$bArgIsArray}));</script>";
1162
            $nC++;
1163
        }
1164
        return $szReturn;
1165
    }
1166
1167
    private function buildJSData()
1168
    {
1169
        $conf = $this->conf;
0 ignored issues
show
Unused Code introduced by
The assignment to $conf is dead and can be removed.
Loading history...
1170
        $misc = $this->misc;
1171
        $lang = $this->lang;
0 ignored issues
show
Unused Code introduced by
The assignment to $lang is dead and can be removed.
Loading history...
1172
        $data = $misc->getDatabaseAccessor();
1173
1174
        $arrayModes  = ['IN', 'OUT', 'INOUT'];
1175
        $arrayTypes  = $data->getTypes(true, true, true);
1176
        $arrayPTypes = [];
1177
        $arrayPModes = [];
1178
        $szTypes     = '';
0 ignored issues
show
Unused Code introduced by
The assignment to $szTypes is dead and can be removed.
Loading history...
1179
1180
        while (!$arrayTypes->EOF) {
1181
            $arrayPTypes[] = "'" . $arrayTypes->fields['typname'] . "'";
1182
            $arrayTypes->moveNext();
1183
        }
1184
1185
        foreach ($arrayModes as $pV) {
1186
            $arrayPModes[] = "'{$pV}'";
1187
        }
1188
1189
        $szTypes = 'g_main_types = new Array(' . implode(',', $arrayPTypes) . ');';
1190
        $szModes = 'g_main_modes = new Array(' . implode(',', $arrayPModes) . ');';
1191
        return $szTypes . $szModes;
1192
    }
1193
}
1194