Passed
Pull Request — master (#70)
by Felipe
03:51
created

Misc::getDatabaseAccessor()   D

Complexity

Conditions 13
Paths 26

Size

Total Lines 83
Code Lines 42

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 13
eloc 42
nc 26
nop 2
dl 0
loc 83
rs 4.9922
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;
4
5
use PHPPgAdmin\Decorators\Decorator;
6
7
/**
8
 * Class to hold various commonly used functions.
9
 *
10
 * $Id: Misc.php,v 1.171 2008/03/17 21:35:48 ioguix Exp $
11
 */
12
class Misc
13
{
14
    use \PHPPgAdmin\HelperTrait;
15
16
    private $_connection = null;
17
    private $_no_db_connection = false;
18
    private $_reload_browser = false;
19
    private $app = null;
0 ignored issues
show
Unused Code introduced by
The property $app is not used and could be removed.

This check marks private properties in classes that are never used. Those properties can be removed.

Loading history...
20
    private $data = null;
21
    private $database = null;
22
    private $server_id = null;
23
    public $appLangFiles = [];
24
    public $appName = '';
25
    public $appVersion = '';
26
    public $form = '';
27
    public $href = '';
28
    public $_name = 'Misc';
29
    public $lang = [];
30
    private $server_info = null;
31
    private $error_msg = '';
32
33
    private $container = null;
34
35
    /* Constructor */
36
    public function __construct(\Slim\Container $container)
37
    {
38
        $this->container = $container;
39
40
        $this->lang = $container->get('lang');
41
        $this->conf = $container->get('conf');
42
        //$this->view           = $container->get('view');
43
        $this->plugin_manager = $container->get('plugin_manager');
44
        $this->appLangFiles = $container->get('appLangFiles');
45
46
        $this->appName = $container->get('settings')['appName'];
47
        $this->appVersion = $container->get('settings')['appVersion'];
48
        $this->postgresqlMinVer = $container->get('settings')['postgresqlMinVer'];
49
        $this->phpMinVer = $container->get('settings')['phpMinVer'];
50
51
        $base_version = $container->get('settings')['base_version'];
52
53
        // Check for config file version mismatch
54
        if (!isset($this->conf['version']) || $base_version > $this->conf['version']) {
55
            $container->get('utils')->addError($this->lang['strbadconfig']);
56
        }
57
58
        // Check database support is properly compiled in
59
        if (!function_exists('pg_connect')) {
60
            $container->get('utils')->addError($this->lang['strnotloaded']);
61
        }
62
63
        // Check the version of PHP
64
        if (version_compare(phpversion(), $this->phpMinVer, '<')) {
65
            $container->get('utils')->addError(sprintf('Version of PHP not supported. Please upgrade to version %s or later.', $this->phpMinVer));
66
        }
67
68
        if (count($this->conf['servers']) === 1) {
69
            $info = $this->conf['servers'][0];
70
            $this->server_id = $info['host'].':'.$info['port'].':'.$info['sslmode'];
71
        } elseif (isset($_REQUEST['server'])) {
72
            $this->server_id = $_REQUEST['server'];
73
        } elseif (isset($_SESSION['webdbLogin']) && count($_SESSION['webdbLogin']) > 0) {
74
            $this->server_id = array_keys($_SESSION['webdbLogin'])[0];
75
        }
76
    }
77
78
    /**
79
     * Sets the view instance property of this class.
80
     *
81
     * @param \Slim\Views\Twig $view [description]
82
     */
83
    public function setView(\Slim\Views\Twig $view)
84
    {
85
        $this->view = $view;
86
    }
87
88
    /**
89
     * Adds or modifies a key in the $conf instance property of this class.
90
     *
91
     * @param string $key   [description]
92
     * @param mixed  $value [description]
93
     *
94
     * @return $this
95
     */
96
    public function setConf(string $key, $value)
97
    {
98
        $this->conf[$key] = $value;
99
100
        return $this;
101
    }
102
103
    /**
104
     * gets the value of a config property, or the array of all config properties.
105
     *
106
     * @param mixed $key value of the key to be retrieved. If null, the full array is returnes
107
     *
108
     * @return mixed the whole $conf array, the value of $conf[key] or null if said key does not exist
109
     */
110
    public function getConf($key = null)
111
    {
112
        if ($key === null) {
113
            return $this->conf;
114
        } elseif (array_key_exists($key, $this->conf)) {
115
            return $this->conf[$key];
116
        }
117
    }
118
119
    public function getServerId()
120
    {
121
        return $this->server_id;
122
    }
123
124
    /**
125
     * Displays link to the context help.
126
     *
127
     * @param $str   - the string that the context help is related to (already escaped)
128
     * @param $help  - help section identifier
129
     * @param $do_print true to echo, false to return
130
     */
131
    public function printHelp($str, $help = null, $do_print = true)
132
    {
133
        //\PC::debug(['str' => $str, 'help' => $help], 'printHelp');
134
        if ($help !== null) {
135
            $helplink = $this->getHelpLink($help);
136
            $str .= '<a class="help" href="'.$helplink.'" title="'.$this->lang['strhelp'].'" target="phppgadminhelp">'.$this->lang['strhelpicon'].'</a>';
137
        }
138
        if ($do_print) {
139
            echo $str;
140
        } else {
141
            return $str;
142
        }
143
    }
144
145
    public function getHelpLink($help)
146
    {
147
        return htmlspecialchars(SUBFOLDER.'/help?help='.urlencode($help).'&server='.urlencode($this->getServerId()));
148
    }
149
150
    /**
151
     * [setReloadBrowser description].
152
     *
153
     * @param bool $flag sets internal $_reload_browser var which will be passed to the footer methods
154
     *
155
     * @return $this
156
     */
157
    public function setReloadBrowser($flag)
158
    {
159
        $this->_reload_browser = boolval($flag);
160
161
        return $this;
162
    }
163
164
    public function getReloadBrowser()
165
    {
166
        return $this->_reload_browser;
167
    }
168
169
    /**
170
     * Default Error Handler. This will be called with the following params.
171
     *
172
     * @param $dbms         the RDBMS you are connecting to
173
     * @param $fn           the name of the calling function (in uppercase)
174
     * @param $errno        the native error number from the database
175
     * @param $errmsg       the native error msg from the database
176
     * @param $p1           $fn specific parameter - see below
177
     * @param $p2
178
     * @param $thisConnection
179
     *
180
     * @throws \PHPPgAdmin\ADOdbException
181
     *
182
     * @internal param $P2 $fn specific parameter - see below
183
     */
0 ignored issues
show
Documentation Bug introduced by
The doc comment $p1 at position 0 could not be parsed: Unknown type name '$p1' at position 0 in $p1.
Loading history...
184
    public static function adodb_throw($dbms, $fn, $errno, $errmsg, $p1, $p2, $thisConnection)
185
    {
186
        if (error_reporting() == 0) {
187
            return;
188
        }
189
190
        $backtrace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS, 2);
191
192
        $btarray0 = [
193
            'msg'      => 'ADOdbException at ',
194
            'class'    => $backtrace[1]['class'],
195
            'type'     => $backtrace[1]['type'],
196
            'function' => $backtrace[1]['function'],
197
            'spacer'   => ' ',
198
            'line'     => $backtrace[0]['line'],
199
        ];
200
201
        $errmsg = htmlspecialchars(\PHPPgAdmin\HelperTrait::br2ln($errmsg));
202
        $p1 = htmlspecialchars(\PHPPgAdmin\HelperTrait::br2ln($p1));
203
        $p2 = htmlspecialchars(\PHPPgAdmin\HelperTrait::br2ln($p2));
204
        switch ($fn) {
205
            case 'EXECUTE':
206
                $sql = $p1;
207
                $inputparams = $p2;
208
209
                $error_msg = '<p><b>strsqlerror</b><br />'.nl2br($errmsg).'</p> <p><b>SQL:</b><br />'.nl2br($sql).'</p>	';
210
211
                echo '<table class="error" cellpadding="5"><tr><td>'.nl2br($error_msg).'</td></tr></table><br />'."\n";
212
213
                break;
214
215
            case 'PCONNECT':
216
            case 'CONNECT':
217
                // do nothing;
218
                break;
219
            default:
220
                $s = "$dbms error: [$errno: $errmsg] in $fn($p1, $p2)\n";
221
                echo "<table class=\"error\" cellpadding=\"5\"><tr><td>{$s}</td></tr></table><br />\n";
222
                break;
223
        }
224
225
        $tag = implode('', $btarray0);
226
227
        \PC::debug(['errno' => $errno, 'fn' => $fn, 'errmsg' => $errmsg], $tag);
228
229
        throw new \PHPPgAdmin\ADOdbException($dbms, $fn, $errno, $errmsg, $p1, $p2, $thisConnection);
230
    }
231
232
    public function getContainer()
233
    {
234
        return $this->container;
235
    }
236
237
    /**
238
     * sets $_no_db_connection boolean value, allows to render scripts that do not need an active session.
239
     *
240
     * @param bool $flag [description]
241
     *
242
     * @return $this
243
     */
244
    public function setNoDBConnection($flag)
245
    {
246
        $this->_no_db_connection = boolval($flag);
247
248
        return $this;
249
    }
250
251
    public function getNoDBConnection()
252
    {
253
        return $this->_no_db_connection;
254
    }
255
256
    /**
257
     * Sets the last error message to display afterwards instead of just dying with the error msg.
258
     *
259
     * @param [string] $msg error message string
260
     */
0 ignored issues
show
Documentation Bug introduced by
The doc comment [string] at position 0 could not be parsed: Unknown type name '[' at position 0 in [string].
Loading history...
261
    public function setErrorMsg($msg)
262
    {
263
        $this->error_msg = $msg;
264
265
        return $this;
266
    }
267
268
    public function getErrorMsg()
269
    {
270
        return $this->error_msg;
271
    }
272
273
    /**
274
     * Creates a database accessor.
275
     *
276
     * @param string $database
277
     * @param null   $server_id
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $server_id is correct as it would always require null to be passed?
Loading history...
278
     *
279
     * @return null
280
     */
281
    public function getDatabaseAccessor($database = '', $server_id = null)
282
    {
283
        $lang = $this->lang;
284
285
        if ($server_id !== null) {
286
            $this->server_id = $server_id;
287
        }
288
289
        $server_info = $this->getServerInfo($this->server_id);
290
291
        if ($this->_no_db_connection || !isset($server_info['username'])) {
292
            return;
293
        }
294
295
        if ($this->data === null) {
296
            try {
297
                $_connection = $this->getConnection($database, $this->server_id);
298
            } catch (\Exception $e) {
299
                $this->setServerInfo(null, null, $this->server_id);
300
                $this->setNoDBConnection(true);
301
                $this->setErrorMsg($e->getMessage());
302
303
                return;
304
            }
305
306
            //$this->prtrace('_connection', $_connection);
307
            if (!$_connection) {
308
                $this->container->utils->addError($lang['strloginfailed']);
309
                $this->setErrorMsg($lang['strloginfailed']);
310
311
                return;
312
            }
313
            // Get the name of the database driver we need to use.
314
            // The description of the server is returned in $platform.
315
            $_type = $_connection->getDriver($platform);
316
317
            //$this->prtrace(['type' => $_type, 'platform' => $platform, 'pgVersion' => $_connection->conn->pgVersion]);
318
319
            if ($_type === null) {
320
                $errormsg = sprintf($lang['strpostgresqlversionnotsupported'], $this->postgresqlMinVer);
321
                $this->container->utils->addError($errormsg);
322
                $this->setErrorMsg($errormsg);
323
324
                return;
325
            }
326
            $_type = '\PHPPgAdmin\Database\\'.$_type;
327
328
            $this->setServerInfo('platform', $platform, $this->server_id);
329
            $this->setServerInfo('pgVersion', $_connection->conn->pgVersion, $this->server_id);
330
331
            // Create a database wrapper class for easy manipulation of the
332
            // connection.
333
334
            $this->data = new $_type($_connection->conn, $this->conf);
335
            $this->data->platform = $_connection->platform;
336
            $this->data->server_info = $server_info;
337
            $this->data->conf = $this->conf;
338
            $this->data->lang = $this->lang;
339
340
            //$this->data->getHelpPages();
341
342
            //$this->prtrace('help_page has ' . count($this->data->help_page) . ' items');
343
344
            /* we work on UTF-8 only encoding */
345
            $this->data->execute("SET client_encoding TO 'UTF-8'");
346
347
            if ($this->data->hasByteaHexDefault()) {
348
                $this->data->execute('SET bytea_output TO escape');
349
            }
350
        }
351
352
        if ($this->_no_db_connection === false && $this->getDatabase() !== null && isset($_REQUEST['schema'])) {
353
            $status = $this->data->setSchema($_REQUEST['schema']);
354
355
            if ($status != 0) {
356
                $this->container->utils->addError($this->lang['strbadschema']);
357
                $this->setErrorMsg($this->lang['strbadschema']);
358
359
                return;
360
            }
361
        }
362
363
        return $this->data;
364
    }
365
366
    public function getConnection($database = '', $server_id = null)
367
    {
368
        $lang = $this->lang;
369
370
        if ($this->_connection === null) {
371
            if ($server_id !== null) {
372
                $this->server_id = $server_id;
373
            }
374
            $server_info = $this->getServerInfo($this->server_id);
375
            $database_to_use = $this->getDatabase($database);
376
377
            // Perform extra security checks if this config option is set
378
            if ($this->conf['extra_login_security']) {
379
                // Disallowed logins if extra_login_security is enabled.
380
                // These must be lowercase.
381
                $bad_usernames = [
382
                    'pgsql'         => 'pgsql',
383
                    'postgres'      => 'postgres',
384
                    'root'          => 'root',
385
                    'administrator' => 'administrator',
386
                ];
387
388
                if (isset($server_info['username']) && array_key_exists(strtolower($server_info['username']), $bad_usernames)) {
389
                    $msg = $lang['strlogindisallowed'];
390
391
                    throw new \Exception($msg);
392
                }
393
394
                if (!isset($server_info['password']) || $server_info['password'] == '') {
395
                    $msg = $lang['strlogindisallowed'];
396
397
                    throw new \Exception($msg);
398
                }
399
            }
400
401
            try {
402
                // Create the connection object and make the connection
403
                $this->_connection = new \PHPPgAdmin\Database\Connection(
404
                    $server_info['host'],
405
                    $server_info['port'],
406
                    $server_info['sslmode'],
407
                    $server_info['username'],
408
                    $server_info['password'],
409
                    $database_to_use
410
                );
411
            } catch (\PHPPgAdmin\ADOdbException $e) {
412
                throw new \Exception($lang['strloginfailed']);
413
            }
414
        }
415
416
        return $this->_connection;
417
    }
418
419
    /**
420
     * Validate and retrieve information on a server.
421
     * If the parameter isn't supplied then the currently
422
     * connected server is returned.
423
     *
424
     * @param $server_id A server identifier (host:port)
425
     *
426
     * @return An associative array of server properties
427
     */
428
    public function getServerInfo($server_id = null)
429
    {
430
431
        //\PC::debug(['$server_id' => $server_id]);
432
433
        if ($server_id !== null) {
434
            $this->server_id = $server_id;
435
        } elseif ($this->server_info !== null) {
436
            return $this->server_info;
437
        }
438
439
        // Check for the server in the logged-in list
440
        if (isset($_SESSION['webdbLogin'][$this->server_id])) {
441
            $this->server_info = $_SESSION['webdbLogin'][$this->server_id];
442
443
            return $this->server_info;
444
        }
445
446
        // Otherwise, look for it in the conf file
447
        foreach ($this->conf['servers'] as $idx => $info) {
448
            if ($this->server_id == $info['host'].':'.$info['port'].':'.$info['sslmode']) {
449
                // Automatically use shared credentials if available
450
                if (!isset($info['username']) && isset($_SESSION['sharedUsername'])) {
451
                    $info['username'] = $_SESSION['sharedUsername'];
452
                    $info['password'] = $_SESSION['sharedPassword'];
453
                    $this->setReloadBrowser(true);
454
                    $this->setServerInfo(null, $info, $this->server_id);
455
                }
456
                $this->server_info = $info;
457
458
                return $this->server_info;
459
            }
460
        }
461
462
        if ($server_id === null) {
463
            $this->server_info = null;
464
465
            return $this->server_info;
466
        }
467
468
        $this->server_info = null;
469
        // Unable to find a matching server, are we being hacked?
470
        echo $this->lang['strinvalidserverparam'];
471
472
        exit;
473
    }
474
475
    /**
476
     * Set server information.
477
     *
478
     * @param $key parameter name to set, or null to replace all
479
     *             params with the assoc-array in $value.
480
     * @param $value the new value, or null to unset the parameter
481
     * @param $server_id the server identifier, or null for current
482
     *                   server.
483
     */
484
    public function setServerInfo($key, $value, $server_id = null)
485
    {
486
        //\PC::debug('setsetverinfo');
487
        if ($server_id === null && isset($_REQUEST['server'])) {
488
            $server_id = $_REQUEST['server'];
489
        }
490
491
        if ($key === null) {
492 View Code Duplication
            if ($value === null) {
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...
493
                unset($_SESSION['webdbLogin'][$server_id]);
494
            } else {
495
                //\PC::debug(['server_id' => $server_id, 'value' => $value], 'webdbLogin null key');
496
                $_SESSION['webdbLogin'][$server_id] = $value;
497
            }
498 View Code Duplication
        } else {
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...
499
            if ($value === null) {
500
                unset($_SESSION['webdbLogin'][$server_id][$key]);
501
            } else {
502
                //\PC::debug(['server_id' => $server_id, 'key' => $key, 'value' => $value], __FILE__ . ' ' . __LINE__ . ' webdbLogin key ' . $key);
503
                $_SESSION['webdbLogin'][$server_id][$key] = $value;
504
            }
505
        }
506
    }
507
508
    public function getDatabase($database = '')
509
    {
510
        if ($this->server_id === null && !isset($_REQUEST['database'])) {
511
            return;
512
        }
513
514
        $server_info = $this->getServerInfo($this->server_id);
515
516
        if ($this->server_id !== null && isset($server_info['useonlydefaultdb']) && $server_info['useonlydefaultdb'] === true) {
517
            $this->database = $server_info['defaultdb'];
518
        } elseif ($database !== '') {
519
            $this->database = $database;
520
        } elseif (isset($_REQUEST['database'])) {
521
            // Connect to the current database
522
            $this->database = $_REQUEST['database'];
523
        } else {
524
            // or if one is not specified then connect to the default database.
525
            $this->database = $server_info['defaultdb'];
526
        }
527
528
        return $this->database;
529
    }
530
531
    /**
532
     * Get list of server groups.
533
     *
534
     * @param bool  $recordset return as RecordSet suitable for HTMLTableController::printTable if true, otherwise just return an array.
535
     * @param mixed $group_id  a group name to filter the returned servers using $this->conf[srv_groups]
536
     *
537
     * @return array|\PHPPgAdmin\ArrayRecordSet either an array or a Recordset suitable for HTMLTableController::printTable
538
     */
539
    public function getServersGroups($recordset = false, $group_id = false)
540
    {
541
        $lang = $this->lang;
542
        $grps = [];
543
544
        if (isset($this->conf['srv_groups'])) {
545
            foreach ($this->conf['srv_groups'] as $i => $group) {
546
                if (
547
                    (($group_id === false) and (!isset($group['parents']))) /* root */
548
                    or (
549
                        ($group_id !== false)
550
                        and isset($group['parents'])
551
                        and in_array($group_id, explode(',',
552
                            preg_replace('/\s/', '', $group['parents'])
553
                        ))
554
                    ) /* nested group */
555
                ) {
556
                    $grps[$i] = [
557
                        'id'     => $i,
558
                        'desc'   => $group['desc'],
559
                        'icon'   => 'Servers',
560
                        'action' => Decorator::url('/views/servers',
561
                            [
562
                                'group' => Decorator::field('id'),
563
                            ]
564
                        ),
565
                        'branch' => Decorator::url('/tree/servers',
566
                            [
567
                                'group' => $i,
568
                            ]
569
                        ),
570
                    ];
571
                }
572
            }
573
574
            if ($group_id === false) {
575
                $grps['all'] = [
576
                    'id'     => 'all',
577
                    'desc'   => $lang['strallservers'],
578
                    'icon'   => 'Servers',
579
                    'action' => Decorator::url('/views/servers',
580
                        [
581
                            'group' => Decorator::field('id'),
582
                        ]
583
                    ),
584
                    'branch' => Decorator::url('/tree/servers',
585
                        [
586
                            'group' => 'all',
587
                        ]
588
                    ),
589
                ];
590
            }
591
        }
592
593
        if ($recordset) {
594
            return new ArrayRecordSet($grps);
595
        }
596
597
        return $grps;
598
    }
599
600
    /**
601
     * Get list of servers.
602
     *
603
     * @param bool  $recordset return as RecordSet suitable for HTMLTableController::printTable if true, otherwise just return an array.
604
     * @param mixed $group     a group name to filter the returned servers using $this->conf[srv_groups]
605
     *
606
     * @return array|\PHPPgAdmin\ArrayRecordSet either an array or a Recordset suitable for HTMLTableController::printTable
607
     */
608
    public function getServers($recordset = false, $group = false)
609
    {
610
        $logins = isset($_SESSION['webdbLogin']) && is_array($_SESSION['webdbLogin']) ? $_SESSION['webdbLogin'] : [];
611
        $srvs = [];
612
613
        if (($group !== false) && ($group !== 'all')) {
614
            if (isset($this->conf['srv_groups'][$group]['servers'])) {
615
                $group = array_fill_keys(explode(',', preg_replace('/\s/', '',
616
                    $this->conf['srv_groups'][$group]['servers'])), 1);
617
            } else {
618
                $group = '';
619
            }
620
        }
621
622
        foreach ($this->conf['servers'] as $idx => $info) {
623
            $server_id = $info['host'].':'.$info['port'].':'.$info['sslmode'];
624
            if ($group === false || isset($group[$idx]) || ($group === 'all')) {
625
                $server_id = $info['host'].':'.$info['port'].':'.$info['sslmode'];
626
627
                if (isset($logins[$server_id])) {
628
                    $srvs[$server_id] = $logins[$server_id];
629
                } else {
630
                    $srvs[$server_id] = $info;
631
                }
632
633
                $srvs[$server_id]['id'] = $server_id;
634
                $srvs[$server_id]['action'] = Decorator::url('/redirect/server',
635
                    [
636
                        'server' => Decorator::field('id'),
637
                    ]
638
                );
639
                if (isset($srvs[$server_id]['username'])) {
640
                    $srvs[$server_id]['icon'] = 'Server';
641
                    $srvs[$server_id]['branch'] = Decorator::url('/src/views/alldb',
642
                        [
643
                            'action'  => 'tree',
644
                            'subject' => 'server',
645
                            'server'  => Decorator::field('id'),
646
                        ]
647
                    );
648
                } else {
649
                    $srvs[$server_id]['icon'] = 'DisconnectedServer';
650
                    $srvs[$server_id]['branch'] = false;
651
                }
652
            }
653
        }
654
655
        uasort($srvs, ['self', '_cmp_desc']);
656
657
        if ($recordset) {
658
            return new ArrayRecordSet($srvs);
659
        }
660
661
        return $srvs;
662
    }
663
664
    /**
665
     * Set the current schema.
666
     *
667
     * @param $schema The schema name
668
     *
669
     * @return int 0 on success
670
     */
671
    public function setCurrentSchema($schema)
672
    {
673
        $data = $this->getDatabaseAccessor();
674
675
        $status = $data->setSchema($schema);
676
        if ($status != 0) {
677
            return $status;
678
        }
679
680
        $_REQUEST['schema'] = $schema;
681
        $this->setHREF();
682
683
        return 0;
684
    }
685
686
    public static function _cmp_desc($a, $b)
687
    {
688
        return strcmp($a['desc'], $b['desc']);
689
    }
690
691
    /**
692
     * Checks if dumps are properly set up.
693
     *
694
     * @param $all (optional) True to check pg_dumpall, false to just check pg_dump
695
     *
696
     * @return True, dumps are set up, false otherwise
697
     */
698
    public function isDumpEnabled($all = false)
699
    {
700
        $info = $this->getServerInfo();
701
702
        return !empty($info[$all ? 'pg_dumpall_path' : 'pg_dump_path']);
703
    }
704
705
    /**
706
     * Sets the href tracking variable.
707
     */
708
    public function setHREF()
709
    {
710
        $this->href = $this->getHREF();
711
        //\PC::debug($this->href, 'Misc::href');
712
        return $this;
713
    }
714
715
    /**
716
     * Get a href query string, excluding objects below the given object type (inclusive).
717
     *
718
     * @param null $exclude_from
0 ignored issues
show
Documentation Bug introduced by
Are you sure the doc-type for parameter $exclude_from is correct as it would always require null to be passed?
Loading history...
719
     *
720
     * @return string
721
     */
722
    public function getHREF($exclude_from = null)
723
    {
724
        $href = [];
725 View Code Duplication
        if (isset($_REQUEST['server']) && $exclude_from != 'server') {
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...
726
            $href[] = 'server='.urlencode($_REQUEST['server']);
727
        }
728 View Code Duplication
        if (isset($_REQUEST['database']) && $exclude_from != 'database') {
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...
729
            $href[] = 'database='.urlencode($_REQUEST['database']);
730
        }
731 View Code Duplication
        if (isset($_REQUEST['schema']) && $exclude_from != 'schema') {
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...
732
            $href[] = 'schema='.urlencode($_REQUEST['schema']);
733
        }
734
735
        return htmlentities(implode('&', $href));
736
    }
737
738
    public function getSubjectParams($subject)
739
    {
740
        $plugin_manager = $this->plugin_manager;
741
742
        $vars = [];
743
744
        switch ($subject) {
745
            case 'root':
746
                $vars = [
747
                    'params' => [
748
                        'subject' => 'root',
749
                    ],
750
                ];
751
                break;
752
            case 'server':
753
                $vars = ['params' => [
754
                    'server'  => $_REQUEST['server'],
755
                    'subject' => 'server',
756
                ]];
757
                break;
758
            case 'role':
759
                $vars = ['params' => [
760
                    'server'   => $_REQUEST['server'],
761
                    'subject'  => 'role',
762
                    'action'   => 'properties',
763
                    'rolename' => $_REQUEST['rolename'],
764
                ]];
765
                break;
766
            case 'database':
767
                $vars = ['params' => [
768
                    'server'   => $_REQUEST['server'],
769
                    'subject'  => 'database',
770
                    'database' => $_REQUEST['database'],
771
                ]];
772
                break;
773
            case 'schema':
774
                $vars = ['params' => [
775
                    'server'   => $_REQUEST['server'],
776
                    'subject'  => 'schema',
777
                    'database' => $_REQUEST['database'],
778
                    'schema'   => $_REQUEST['schema'],
779
                ]];
780
                break;
781
            case 'table':
782
                $vars = ['params' => [
783
                    'server'   => $_REQUEST['server'],
784
                    'subject'  => 'table',
785
                    'database' => $_REQUEST['database'],
786
                    'schema'   => $_REQUEST['schema'],
787
                    'table'    => $_REQUEST['table'],
788
                ]];
789
                break;
790 View Code Duplication
            case 'selectrows':
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...
791
                $vars = [
792
                    'url'    => 'tables.php',
793
                    'params' => [
794
                        'server'   => $_REQUEST['server'],
795
                        'subject'  => 'table',
796
                        'database' => $_REQUEST['database'],
797
                        'schema'   => $_REQUEST['schema'],
798
                        'table'    => $_REQUEST['table'],
799
                        'action'   => 'confselectrows',
800
                    ], ];
801
                break;
802
            case 'view':
803
                $vars = ['params' => [
804
                    'server'   => $_REQUEST['server'],
805
                    'subject'  => 'view',
806
                    'database' => $_REQUEST['database'],
807
                    'schema'   => $_REQUEST['schema'],
808
                    'view'     => $_REQUEST['view'],
809
                ]];
810
                break;
811
            case 'matview':
812
                $vars = ['params' => [
813
                    'server'   => $_REQUEST['server'],
814
                    'subject'  => 'matview',
815
                    'database' => $_REQUEST['database'],
816
                    'schema'   => $_REQUEST['schema'],
817
                    'matview'  => $_REQUEST['matview'],
818
                ]];
819
                break;
820
821
            case 'fulltext':
822 View Code Duplication
            case 'ftscfg':
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...
823
                $vars = ['params' => [
824
                    'server'   => $_REQUEST['server'],
825
                    'subject'  => 'fulltext',
826
                    'database' => $_REQUEST['database'],
827
                    'schema'   => $_REQUEST['schema'],
828
                    'action'   => 'viewconfig',
829
                    'ftscfg'   => $_REQUEST['ftscfg'],
830
                ]];
831
                break;
832 View Code Duplication
            case 'function':
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...
833
                $vars = ['params' => [
834
                    'server'       => $_REQUEST['server'],
835
                    'subject'      => 'function',
836
                    'database'     => $_REQUEST['database'],
837
                    'schema'       => $_REQUEST['schema'],
838
                    'function'     => $_REQUEST['function'],
839
                    'function_oid' => $_REQUEST['function_oid'],
840
                ]];
841
                break;
842 View Code Duplication
            case 'aggregate':
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...
843
                $vars = ['params' => [
844
                    'server'   => $_REQUEST['server'],
845
                    'subject'  => 'aggregate',
846
                    'action'   => 'properties',
847
                    'database' => $_REQUEST['database'],
848
                    'schema'   => $_REQUEST['schema'],
849
                    'aggrname' => $_REQUEST['aggrname'],
850
                    'aggrtype' => $_REQUEST['aggrtype'],
851
                ]];
852
                break;
853
            case 'column':
854
                if (isset($_REQUEST['table'])) {
855
                    $vars = ['params' => [
856
                        'server'   => $_REQUEST['server'],
857
                        'subject'  => 'column',
858
                        'database' => $_REQUEST['database'],
859
                        'schema'   => $_REQUEST['schema'],
860
                        'table'    => $_REQUEST['table'],
861
                        'column'   => $_REQUEST['column'],
862
                    ]];
863
                } else {
864
                    $vars = ['params' => [
865
                        'server'   => $_REQUEST['server'],
866
                        'subject'  => 'column',
867
                        'database' => $_REQUEST['database'],
868
                        'schema'   => $_REQUEST['schema'],
869
                        'view'     => $_REQUEST['view'],
870
                        'column'   => $_REQUEST['column'],
871
                    ]];
872
                }
873
874
                break;
875
            case 'plugin':
876
                $vars = [
877
                    'url'    => 'plugin.php',
878
                    'params' => [
879
                        'server'  => $_REQUEST['server'],
880
                        'subject' => 'plugin',
881
                        'plugin'  => $_REQUEST['plugin'],
882
                    ], ];
883
884
                if (!is_null($plugin_manager->getPlugin($_REQUEST['plugin']))) {
885
                    $vars['params'] = array_merge($vars['params'], $plugin_manager->getPlugin($_REQUEST['plugin'])->get_subject_params());
886
                }
887
888
                break;
889
            default:
890
                return false;
891
        }
892
893
        if (!isset($vars['url'])) {
894
            $vars['url'] = SUBFOLDER.'/redirect';
895
        }
896
        if ($vars['url'] == SUBFOLDER.'/redirect' && isset($vars['params']['subject'])) {
897
            $vars['url'] = SUBFOLDER.'/redirect/'.$vars['params']['subject'];
898
            unset($vars['params']['subject']);
899
        }
900
901
        return $vars;
902
    }
903
904
    /**
905
     * Sets the form tracking variable.
906
     */
907
    public function setForm()
908
    {
909
        $form = [];
910
        if (isset($_REQUEST['server'])) {
911
            $form[] = '<input type="hidden" name="server" value="'.htmlspecialchars($_REQUEST['server']).'" />';
912
        }
913
        if (isset($_REQUEST['database'])) {
914
            $form[] = '<input type="hidden" name="database" value="'.htmlspecialchars($_REQUEST['database']).'" />';
915
        }
916
917
        if (isset($_REQUEST['schema'])) {
918
            $form[] = '<input type="hidden" name="schema" value="'.htmlspecialchars($_REQUEST['schema']).'" />';
919
        }
920
        $this->form = implode("\n", $form);
921
922
        return $this->form;
923
924
        //\PC::debug($this->form, 'Misc::form');
925
    }
926
927
    /**
928
     * Render a value into HTML using formatting rules specified
929
     * by a type name and parameters.
930
     *
931
     * @param                        $str    The string to change
932
     * @param                        $type   Field type (optional), this may be an internal PostgreSQL type, or:
933
     *                                       yesno    - same as bool, but renders as 'Yes' or 'No'.
934
     *                                       pre      - render in a <pre> block.
935
     *                                       nbsp     - replace all spaces with &nbsp;'s
936
     *                                       verbatim - render exactly as supplied, no escaping what-so-ever.
937
     *                                       callback - render using a callback function supplied in the 'function' param.
938
     * @param array|\PHPPgAdmin\Type $params Type parameters (optional), known parameters:
939
     *                                       null     - string to display if $str is null, or set to TRUE to use a default 'NULL' string,
940
     *                                       otherwise nothing is rendered.
941
     *                                       clip     - if true, clip the value to a fixed length, and append an ellipsis...
942
     *                                       cliplen  - the maximum length when clip is enabled (defaults to $conf['max_chars'])
943
     *                                       ellipsis - the string to append to a clipped value (defaults to $lang['strellipsis'])
944
     *                                       tag      - an HTML element name to surround the value.
945
     *                                       class    - a class attribute to apply to any surrounding HTML element.
946
     *                                       align    - an align attribute ('left','right','center' etc.)
947
     *                                       true     - (type='bool') the representation of true.
948
     *                                       false    - (type='bool') the representation of false.
949
     *                                       function - (type='callback') a function name, accepts args ($str, $params) and returns a rendering.
950
     *                                       lineno   - prefix each line with a line number.
951
     *                                       map      - an associative array.
952
     *
953
     * @return \PHPPgAdmin\The HTML rendered value
954
     */
955
    public function printVal($str, $type = null, $params = [])
956
    {
957
        $lang = $this->lang;
958
        $data = $this->data;
959
960
        // Shortcircuit for a NULL value
961
        if (is_null($str)) {
962
            return isset($params['null'])
963
            ? ($params['null'] === true ? '<i>NULL</i>' : $params['null'])
964
            : '';
965
        }
966
967
        if (isset($params['map']) && isset($params['map'][$str])) {
968
            $str = $params['map'][$str];
969
        }
970
971
        // Clip the value if the 'clip' parameter is true.
972
        if (isset($params['clip']) && $params['clip'] === true) {
973
            $maxlen = isset($params['cliplen']) && is_int($params['cliplen']) ? $params['cliplen'] : $this->conf['max_chars'];
974
            $ellipsis = isset($params['ellipsis']) ? $params['ellipsis'] : $lang['strellipsis'];
975
            if (strlen($str) > $maxlen) {
976
                $str = substr($str, 0, $maxlen - 1).$ellipsis;
977
            }
978
        }
979
980
        $out = '';
981
982
        switch ($type) {
983
            case 'int2':
984
            case 'int4':
985
            case 'int8':
986
            case 'float4':
987
            case 'float8':
988
            case 'money':
989
            case 'numeric':
990
            case 'oid':
991
            case 'xid':
992
            case 'cid':
993
            case 'tid':
994
                $align = 'right';
995
                $out = nl2br(htmlspecialchars(\PHPPgAdmin\HelperTrait::br2ln($str)));
996
                break;
997
            case 'yesno':
998
                if (!isset($params['true'])) {
999
                    $params['true'] = $lang['stryes'];
1000
                }
1001
1002
                if (!isset($params['false'])) {
1003
                    $params['false'] = $lang['strno'];
1004
                }
1005
1006
            // No break - fall through to boolean case.
1007
            case 'bool':
1008
            case 'boolean':
1009
                if (is_bool($str)) {
1010
                    $str = $str ? 't' : 'f';
1011
                }
1012
1013
                switch ($str) {
1014
                    case 't':
1015
                        $out = (isset($params['true']) ? $params['true'] : $lang['strtrue']);
1016
                        $align = 'center';
1017
                        break;
1018
                    case 'f':
1019
                        $out = (isset($params['false']) ? $params['false'] : $lang['strfalse']);
1020
                        $align = 'center';
1021
                        break;
1022
                    default:
1023
                        $out = htmlspecialchars($str);
1024
                }
1025
                break;
1026
            case 'bytea':
1027
                $tag = 'div';
1028
                $class = 'pre';
1029
                $out = $data->escapeBytea($str);
1030
                break;
1031
            case 'errormsg':
1032
                $tag = 'pre';
1033
                $class = 'error';
1034
                $out = htmlspecialchars($str);
1035
                break;
1036
            case 'pre':
1037
                $tag = 'pre';
1038
                $out = htmlspecialchars($str);
1039
                break;
1040
            case 'prenoescape':
1041
                $tag = 'pre';
1042
                $out = $str;
1043
                break;
1044
            case 'nbsp':
1045
                $out = nl2br(str_replace(' ', '&nbsp;', \PHPPgAdmin\HelperTrait::br2ln($str)));
1046
1047
                break;
1048
            case 'verbatim':
1049
                $out = $str;
1050
                break;
1051
            case 'callback':
1052
                $out = $params['function']($str, $params);
1053
                break;
1054
            case 'prettysize':
1055
                if ($str == -1) {
1056
                    $out = $lang['strnoaccess'];
1057
                } else {
1058
                    $limit = 10 * 1024;
1059
                    $mult = 1;
1060
                    if ($str < $limit * $mult) {
1061
                        $out = $str.' '.$lang['strbytes'];
1062
                    } else {
1063
                        $mult *= 1024;
1064
                        if ($str < $limit * $mult) {
1065
                            $out = floor(($str + $mult / 2) / $mult).' '.$lang['strkb'];
1066
                        } else {
1067
                            $mult *= 1024;
1068
                            if ($str < $limit * $mult) {
1069
                                $out = floor(($str + $mult / 2) / $mult).' '.$lang['strmb'];
1070
                            } else {
1071
                                $mult *= 1024;
1072
                                if ($str < $limit * $mult) {
1073
                                    $out = floor(($str + $mult / 2) / $mult).' '.$lang['strgb'];
1074
                                } else {
1075
                                    $mult *= 1024;
1076
                                    if ($str < $limit * $mult) {
1077
                                        $out = floor(($str + $mult / 2) / $mult).' '.$lang['strtb'];
1078
                                    }
1079
                                }
1080
                            }
1081
                        }
1082
                    }
1083
                }
1084
                break;
1085
            default:
1086
                // If the string contains at least one instance of >1 space in a row, a tab
1087
                // character, a space at the start of a line, or a space at the start of
1088
                // the whole string then render within a pre-formatted element (<pre>).
1089
                if (preg_match('/(^ |  |\t|\n )/m', $str)) {
1090
                    $tag = 'pre';
1091
                    $class = 'data';
1092
                    $out = htmlspecialchars($str);
1093
                } else {
1094
                    $out = nl2br(htmlspecialchars(\PHPPgAdmin\HelperTrait::br2ln($str)));
1095
                }
1096
        }
1097
1098
        if (isset($params['class'])) {
1099
            $class = $params['class'];
1100
        }
1101
1102
        if (isset($params['align'])) {
1103
            $align = $params['align'];
1104
        }
1105
1106
        if (!isset($tag) && (isset($class) || isset($align))) {
1107
            $tag = 'div';
1108
        }
1109
1110
        if (isset($tag)) {
1111
            $alignattr = isset($align) ? " style=\"text-align: {$align}\"" : '';
1112
            $classattr = isset($class) ? " class=\"{$class}\"" : '';
1113
            $out = "<{$tag}{$alignattr}{$classattr}>{$out}</{$tag}>";
1114
        }
1115
1116
        // Add line numbers if 'lineno' param is true
1117
        if (isset($params['lineno']) && $params['lineno'] === true) {
1118
            $lines = explode("\n", $str);
1119
            $num = count($lines);
1120
            if ($num > 0) {
1121
                $temp = "<table>\n<tr><td class=\"{$class}\" style=\"vertical-align: top; padding-right: 10px;\"><pre class=\"{$class}\">";
1122
                for ($i = 1; $i <= $num; $i++) {
1123
                    $temp .= $i."\n";
1124
                }
1125
                $temp .= "</pre></td><td class=\"{$class}\" style=\"vertical-align: top;\">{$out}</td></tr></table>\n";
1126
                $out = $temp;
1127
            }
1128
            unset($lines);
1129
        }
1130
1131
        return $out;
1132
    }
1133
1134
    /**
1135
     * A function to recursively strip slashes.  Used to
1136
     * enforce magic_quotes_gpc being off.
1137
     *
1138
     * @param &var The variable to strip
1139
     */
1140
    public function stripVar(&$var)
1141
    {
1142
        if (is_array($var)) {
1143
            foreach ($var as $k => $v) {
1144
                $this->stripVar($var[$k]);
1145
1146
                /* magic_quotes_gpc escape keys as well ...*/
1147
                if (is_string($k)) {
1148
                    $ek = stripslashes($k);
1149
                    if ($ek !== $k) {
1150
                        $var[$ek] = $var[$k];
1151
                        unset($var[$k]);
1152
                    }
1153
                }
1154
            }
1155
        } else {
1156
            $var = stripslashes($var);
1157
        }
1158
    }
1159
1160
    /**
1161
     * Retrieve the tab info for a specific tab bar.
1162
     *
1163
     * @param $section The name of the tab bar.
1164
     *
1165
     * @return array
1166
     */
1167
    public function getNavTabs($section)
1168
    {
1169
        $data = $this->data;
1170
        $lang = $this->lang;
1171
        $plugin_manager = $this->plugin_manager;
1172
1173
        $hide_advanced = ($this->conf['show_advanced'] === false);
1174
        $tabs = [];
1175
1176
        switch ($section) {
1177
            case 'root':
1178
                $tabs = [
1179
                    'intro'   => [
1180
                        'title' => $lang['strintroduction'],
1181
                        'url'   => 'intro.php',
1182
                        'icon'  => 'Introduction',
1183
                    ],
1184
                    'servers' => [
1185
                        'title' => $lang['strservers'],
1186
                        'url'   => 'servers.php',
1187
                        'icon'  => 'Servers',
1188
                    ],
1189
                ];
1190
                break;
1191
1192
            case 'server':
1193
                $hide_users = true;
1194
                if ($data) {
1195
                    $hide_users = !$data->isSuperUser();
1196
                }
1197
1198
                $tabs = [
1199
                    'databases' => [
1200
                        'title'   => $lang['strdatabases'],
1201
                        'url'     => 'alldb.php',
1202
                        'urlvars' => ['subject' => 'server'],
1203
                        'help'    => 'pg.database',
1204
                        'icon'    => 'Databases',
1205
                    ],
1206
                ];
1207
                if ($data && $data->hasRoles()) {
1208
                    $tabs = array_merge($tabs, [
1209
                        'roles' => [
1210
                            'title'   => $lang['strroles'],
1211
                            'url'     => 'roles.php',
1212
                            'urlvars' => ['subject' => 'server'],
1213
                            'hide'    => $hide_users,
1214
                            'help'    => 'pg.role',
1215
                            'icon'    => 'Roles',
1216
                        ],
1217
                    ]);
1218
                } else {
1219
                    $tabs = array_merge($tabs, [
1220
                        'users'  => [
1221
                            'title'   => $lang['strusers'],
1222
                            'url'     => 'users.php',
1223
                            'urlvars' => ['subject' => 'server'],
1224
                            'hide'    => $hide_users,
1225
                            'help'    => 'pg.user',
1226
                            'icon'    => 'Users',
1227
                        ],
1228
                        'groups' => [
1229
                            'title'   => $lang['strgroups'],
1230
                            'url'     => 'groups.php',
1231
                            'urlvars' => ['subject' => 'server'],
1232
                            'hide'    => $hide_users,
1233
                            'help'    => 'pg.group',
1234
                            'icon'    => 'UserGroups',
1235
                        ],
1236
                    ]);
1237
                }
1238
1239
                $tabs = array_merge($tabs, [
1240
                    'account'     => [
1241
                        'title'   => $lang['straccount'],
1242
                        'url'     => ($data && $data->hasRoles()) ? 'roles.php' : 'users.php',
1243
                        'urlvars' => ['subject' => 'server', 'action' => 'account'],
1244
                        'hide'    => !$hide_users,
1245
                        'help'    => 'pg.role',
1246
                        'icon'    => 'User',
1247
                    ],
1248
                    'tablespaces' => [
1249
                        'title'   => $lang['strtablespaces'],
1250
                        'url'     => 'tablespaces.php',
1251
                        'urlvars' => ['subject' => 'server'],
1252
                        'hide'    => !$data || !$data->hasTablespaces(),
1253
                        'help'    => 'pg.tablespace',
1254
                        'icon'    => 'Tablespaces',
1255
                    ],
1256
                    'export'      => [
1257
                        'title'   => $lang['strexport'],
1258
                        'url'     => 'alldb.php',
1259
                        'urlvars' => ['subject' => 'server', 'action' => 'export'],
1260
                        'hide'    => !$this->isDumpEnabled(),
1261
                        'icon'    => 'Export',
1262
                    ],
1263
                ]);
1264
                break;
1265
            case 'database':
1266
                $tabs = [
1267
                    'schemas'    => [
1268
                        'title'   => $lang['strschemas'],
1269
                        'url'     => 'schemas.php',
1270
                        'urlvars' => ['subject' => 'database'],
1271
                        'help'    => 'pg.schema',
1272
                        'icon'    => 'Schemas',
1273
                    ],
1274
                    'sql'        => [
1275
                        'title'   => $lang['strsql'],
1276
                        'url'     => 'database.php',
1277
                        'urlvars' => ['subject' => 'database', 'action' => 'sql', 'new' => 1],
1278
                        'help'    => 'pg.sql',
1279
                        'tree'    => false,
1280
                        'icon'    => 'SqlEditor',
1281
                    ],
1282
                    'find'       => [
1283
                        'title'   => $lang['strfind'],
1284
                        'url'     => 'database.php',
1285
                        'urlvars' => ['subject' => 'database', 'action' => 'find'],
1286
                        'tree'    => false,
1287
                        'icon'    => 'Search',
1288
                    ],
1289
                    'variables'  => [
1290
                        'title'   => $lang['strvariables'],
1291
                        'url'     => 'database.php',
1292
                        'urlvars' => ['subject' => 'database', 'action' => 'variables'],
1293
                        'help'    => 'pg.variable',
1294
                        'tree'    => false,
1295
                        'icon'    => 'Variables',
1296
                    ],
1297
                    'processes'  => [
1298
                        'title'   => $lang['strprocesses'],
1299
                        'url'     => 'database.php',
1300
                        'urlvars' => ['subject' => 'database', 'action' => 'processes'],
1301
                        'help'    => 'pg.process',
1302
                        'tree'    => false,
1303
                        'icon'    => 'Processes',
1304
                    ],
1305
                    'locks'      => [
1306
                        'title'   => $lang['strlocks'],
1307
                        'url'     => 'database.php',
1308
                        'urlvars' => ['subject' => 'database', 'action' => 'locks'],
1309
                        'help'    => 'pg.locks',
1310
                        'tree'    => false,
1311
                        'icon'    => 'Key',
1312
                    ],
1313
                    'admin'      => [
1314
                        'title'   => $lang['stradmin'],
1315
                        'url'     => 'database.php',
1316
                        'urlvars' => ['subject' => 'database', 'action' => 'admin'],
1317
                        'tree'    => false,
1318
                        'icon'    => 'Admin',
1319
                    ],
1320
                    'privileges' => [
1321
                        'title'   => $lang['strprivileges'],
1322
                        'url'     => 'privileges.php',
1323
                        'urlvars' => ['subject' => 'database'],
1324
                        'hide'    => !isset($data->privlist['database']),
1325
                        'help'    => 'pg.privilege',
1326
                        'tree'    => false,
1327
                        'icon'    => 'Privileges',
1328
                    ],
1329
                    'languages'  => [
1330
                        'title'   => $lang['strlanguages'],
1331
                        'url'     => 'languages.php',
1332
                        'urlvars' => ['subject' => 'database'],
1333
                        'hide'    => $hide_advanced,
1334
                        'help'    => 'pg.language',
1335
                        'icon'    => 'Languages',
1336
                    ],
1337
                    'casts'      => [
1338
                        'title'   => $lang['strcasts'],
1339
                        'url'     => 'casts.php',
1340
                        'urlvars' => ['subject' => 'database'],
1341
                        'hide'    => $hide_advanced,
1342
                        'help'    => 'pg.cast',
1343
                        'icon'    => 'Casts',
1344
                    ],
1345
                    'export'     => [
1346
                        'title'   => $lang['strexport'],
1347
                        'url'     => 'database.php',
1348
                        'urlvars' => ['subject' => 'database', 'action' => 'export'],
1349
                        'hide'    => !$this->isDumpEnabled(),
1350
                        'tree'    => false,
1351
                        'icon'    => 'Export',
1352
                    ],
1353
                ];
1354
                break;
1355
1356
            case 'schema':
1357
                $tabs = [
1358
                    'tables'      => [
1359
                        'title'   => $lang['strtables'],
1360
                        'url'     => 'tables.php',
1361
                        'urlvars' => ['subject' => 'schema'],
1362
                        'help'    => 'pg.table',
1363
                        'icon'    => 'Tables',
1364
                    ],
1365
                    'views'       => [
1366
                        'title'   => $lang['strviews'],
1367
                        'url'     => 'views.php',
1368
                        'urlvars' => ['subject' => 'schema'],
1369
                        'help'    => 'pg.view',
1370
                        'icon'    => 'Views',
1371
                    ],
1372
                    'matviews'    => [
1373
                        'title'   => 'M '.$lang['strviews'],
1374
                        'url'     => 'materializedviews.php',
1375
                        'urlvars' => ['subject' => 'schema'],
1376
                        'help'    => 'pg.matview',
1377
                        'icon'    => 'MViews',
1378
                    ],
1379
                    'sequences'   => [
1380
                        'title'   => $lang['strsequences'],
1381
                        'url'     => 'sequences.php',
1382
                        'urlvars' => ['subject' => 'schema'],
1383
                        'help'    => 'pg.sequence',
1384
                        'icon'    => 'Sequences',
1385
                    ],
1386
                    'functions'   => [
1387
                        'title'   => $lang['strfunctions'],
1388
                        'url'     => 'functions.php',
1389
                        'urlvars' => ['subject' => 'schema'],
1390
                        'help'    => 'pg.function',
1391
                        'icon'    => 'Functions',
1392
                    ],
1393
                    'fulltext'    => [
1394
                        'title'   => $lang['strfulltext'],
1395
                        'url'     => 'fulltext.php',
1396
                        'urlvars' => ['subject' => 'schema'],
1397
                        'help'    => 'pg.fts',
1398
                        'tree'    => true,
1399
                        'icon'    => 'Fts',
1400
                    ],
1401
                    'domains'     => [
1402
                        'title'   => $lang['strdomains'],
1403
                        'url'     => 'domains.php',
1404
                        'urlvars' => ['subject' => 'schema'],
1405
                        'help'    => 'pg.domain',
1406
                        'icon'    => 'Domains',
1407
                    ],
1408
                    'aggregates'  => [
1409
                        'title'   => $lang['straggregates'],
1410
                        'url'     => 'aggregates.php',
1411
                        'urlvars' => ['subject' => 'schema'],
1412
                        'hide'    => $hide_advanced,
1413
                        'help'    => 'pg.aggregate',
1414
                        'icon'    => 'Aggregates',
1415
                    ],
1416
                    'types'       => [
1417
                        'title'   => $lang['strtypes'],
1418
                        'url'     => 'types.php',
1419
                        'urlvars' => ['subject' => 'schema'],
1420
                        'hide'    => $hide_advanced,
1421
                        'help'    => 'pg.type',
1422
                        'icon'    => 'Types',
1423
                    ],
1424
                    'operators'   => [
1425
                        'title'   => $lang['stroperators'],
1426
                        'url'     => 'operators.php',
1427
                        'urlvars' => ['subject' => 'schema'],
1428
                        'hide'    => $hide_advanced,
1429
                        'help'    => 'pg.operator',
1430
                        'icon'    => 'Operators',
1431
                    ],
1432
                    'opclasses'   => [
1433
                        'title'   => $lang['stropclasses'],
1434
                        'url'     => 'opclasses.php',
1435
                        'urlvars' => ['subject' => 'schema'],
1436
                        'hide'    => $hide_advanced,
1437
                        'help'    => 'pg.opclass',
1438
                        'icon'    => 'OperatorClasses',
1439
                    ],
1440
                    'conversions' => [
1441
                        'title'   => $lang['strconversions'],
1442
                        'url'     => 'conversions.php',
1443
                        'urlvars' => ['subject' => 'schema'],
1444
                        'hide'    => $hide_advanced,
1445
                        'help'    => 'pg.conversion',
1446
                        'icon'    => 'Conversions',
1447
                    ],
1448
                    'privileges'  => [
1449
                        'title'   => $lang['strprivileges'],
1450
                        'url'     => 'privileges.php',
1451
                        'urlvars' => ['subject' => 'schema'],
1452
                        'help'    => 'pg.privilege',
1453
                        'tree'    => false,
1454
                        'icon'    => 'Privileges',
1455
                    ],
1456
                    'export'      => [
1457
                        'title'   => $lang['strexport'],
1458
                        'url'     => 'schemas.php',
1459
                        'urlvars' => ['subject' => 'schema', 'action' => 'export'],
1460
                        'hide'    => !$this->isDumpEnabled(),
1461
                        'tree'    => false,
1462
                        'icon'    => 'Export',
1463
                    ],
1464
                ];
1465
                if (!$data->hasFTS()) {
1466
                    unset($tabs['fulltext']);
1467
                }
1468
1469
                break;
1470
1471
            case 'table':
1472
                $tabs = [
1473
                    'columns'     => [
1474
                        'title'   => $lang['strcolumns'],
1475
                        'url'     => 'tblproperties.php',
1476
                        'urlvars' => ['subject' => 'table', 'table' => Decorator::field('table')],
1477
                        'icon'    => 'Columns',
1478
                        'branch'  => true,
1479
                    ],
1480
                    'browse'      => [
1481
                        'title'   => $lang['strbrowse'],
1482
                        'icon'    => 'Columns',
1483
                        'url'     => 'display.php',
1484
                        'urlvars' => ['subject' => 'table', 'table' => Decorator::field('table')],
1485
                        'return'  => 'table',
1486
                        'branch'  => true,
1487
                    ],
1488
                    'select'      => [
1489
                        'title'   => $lang['strselect'],
1490
                        'icon'    => 'Search',
1491
                        'url'     => 'tables.php',
1492
                        'urlvars' => ['subject' => 'table', 'table' => Decorator::field('table'), 'action' => 'confselectrows'],
1493
                        'help'    => 'pg.sql.select',
1494
                    ],
1495
                    'insert'      => [
1496
                        'title'   => $lang['strinsert'],
1497
                        'url'     => 'tables.php',
1498
                        'urlvars' => [
1499
                            'action' => 'confinsertrow',
1500
                            'table'  => Decorator::field('table'),
1501
                        ],
1502
                        'help'    => 'pg.sql.insert',
1503
                        'icon'    => 'Operator',
1504
                    ],
1505
                    'indexes'     => [
1506
                        'title'   => $lang['strindexes'],
1507
                        'url'     => 'indexes.php',
1508
                        'urlvars' => ['subject' => 'table', 'table' => Decorator::field('table')],
1509
                        'help'    => 'pg.index',
1510
                        'icon'    => 'Indexes',
1511
                        'branch'  => true,
1512
                    ],
1513
                    'constraints' => [
1514
                        'title'   => $lang['strconstraints'],
1515
                        'url'     => 'constraints.php',
1516
                        'urlvars' => ['subject' => 'table', 'table' => Decorator::field('table')],
1517
                        'help'    => 'pg.constraint',
1518
                        'icon'    => 'Constraints',
1519
                        'branch'  => true,
1520
                    ],
1521
                    'triggers'    => [
1522
                        'title'   => $lang['strtriggers'],
1523
                        'url'     => 'triggers.php',
1524
                        'urlvars' => ['subject' => 'table', 'table' => Decorator::field('table')],
1525
                        'help'    => 'pg.trigger',
1526
                        'icon'    => 'Triggers',
1527
                        'branch'  => true,
1528
                    ],
1529
                    'rules'       => [
1530
                        'title'   => $lang['strrules'],
1531
                        'url'     => 'rules.php',
1532
                        'urlvars' => ['subject' => 'table', 'table' => Decorator::field('table')],
1533
                        'help'    => 'pg.rule',
1534
                        'icon'    => 'Rules',
1535
                        'branch'  => true,
1536
                    ],
1537
                    'admin'       => [
1538
                        'title'   => $lang['stradmin'],
1539
                        'url'     => 'tables.php',
1540
                        'urlvars' => ['subject' => 'table', 'table' => Decorator::field('table'), 'action' => 'admin'],
1541
                        'icon'    => 'Admin',
1542
                    ],
1543
                    'info'        => [
1544
                        'title'   => $lang['strinfo'],
1545
                        'url'     => 'info.php',
1546
                        'urlvars' => ['subject' => 'table', 'table' => Decorator::field('table')],
1547
                        'icon'    => 'Statistics',
1548
                    ],
1549
                    'privileges'  => [
1550
                        'title'   => $lang['strprivileges'],
1551
                        'url'     => 'privileges.php',
1552
                        'urlvars' => ['subject' => 'table', 'table' => Decorator::field('table')],
1553
                        'help'    => 'pg.privilege',
1554
                        'icon'    => 'Privileges',
1555
                    ],
1556
                    'import'      => [
1557
                        'title'   => $lang['strimport'],
1558
                        'url'     => 'tblproperties.php',
1559
                        'urlvars' => ['subject' => 'table', 'table' => Decorator::field('table'), 'action' => 'import'],
1560
                        'icon'    => 'Import',
1561
                        'hide'    => false,
1562
                    ],
1563
                    'export'      => [
1564
                        'title'   => $lang['strexport'],
1565
                        'url'     => 'tblproperties.php',
1566
                        'urlvars' => ['subject' => 'table', 'table' => Decorator::field('table'), 'action' => 'export'],
1567
                        'icon'    => 'Export',
1568
                        'hide'    => false,
1569
                    ],
1570
                ];
1571
                break;
1572
1573
            case 'view':
1574
                $tabs = [
1575
                    'columns'    => [
1576
                        'title'   => $lang['strcolumns'],
1577
                        'url'     => 'viewproperties.php',
1578
                        'urlvars' => ['subject' => 'view', 'view' => Decorator::field('view')],
1579
                        'icon'    => 'Columns',
1580
                        'branch'  => true,
1581
                    ],
1582
                    'browse'     => [
1583
                        'title'   => $lang['strbrowse'],
1584
                        'icon'    => 'Columns',
1585
                        'url'     => 'display.php',
1586
                        'urlvars' => [
1587
                            'action'  => 'confselectrows',
1588
                            'return'  => 'schema',
1589
                            'subject' => 'view',
1590
                            'view'    => Decorator::field('view'),
1591
                        ],
1592
                        'branch'  => true,
1593
                    ],
1594
                    'select'     => [
1595
                        'title'   => $lang['strselect'],
1596
                        'icon'    => 'Search',
1597
                        'url'     => 'views.php',
1598
                        'urlvars' => ['action' => 'confselectrows', 'view' => Decorator::field('view')],
1599
                        'help'    => 'pg.sql.select',
1600
                    ],
1601
                    'definition' => [
1602
                        'title'   => $lang['strdefinition'],
1603
                        'url'     => 'viewproperties.php',
1604
                        'urlvars' => ['subject' => 'view', 'view' => Decorator::field('view'), 'action' => 'definition'],
1605
                        'icon'    => 'Definition',
1606
                    ],
1607
                    'rules'      => [
1608
                        'title'   => $lang['strrules'],
1609
                        'url'     => 'rules.php',
1610
                        'urlvars' => ['subject' => 'view', 'view' => Decorator::field('view')],
1611
                        'help'    => 'pg.rule',
1612
                        'icon'    => 'Rules',
1613
                        'branch'  => true,
1614
                    ],
1615
                    'privileges' => [
1616
                        'title'   => $lang['strprivileges'],
1617
                        'url'     => 'privileges.php',
1618
                        'urlvars' => ['subject' => 'view', 'view' => Decorator::field('view')],
1619
                        'help'    => 'pg.privilege',
1620
                        'icon'    => 'Privileges',
1621
                    ],
1622
                    'export'     => [
1623
                        'title'   => $lang['strexport'],
1624
                        'url'     => 'viewproperties.php',
1625
                        'urlvars' => ['subject' => 'view', 'view' => Decorator::field('view'), 'action' => 'export'],
1626
                        'icon'    => 'Export',
1627
                        'hide'    => false,
1628
                    ],
1629
                ];
1630
                break;
1631
1632
            case 'matview':
1633
                $tabs = [
1634
                    'columns'    => [
1635
                        'title'   => $lang['strcolumns'],
1636
                        'url'     => 'materializedviewproperties.php',
1637
                        'urlvars' => ['subject' => 'matview', 'matview' => Decorator::field('matview')],
1638
                        'icon'    => 'Columns',
1639
                        'branch'  => true,
1640
                    ],
1641
                    'browse'     => [
1642
                        'title'   => $lang['strbrowse'],
1643
                        'icon'    => 'Columns',
1644
                        'url'     => 'display.php',
1645
                        'urlvars' => [
1646
                            'action'  => 'confselectrows',
1647
                            'return'  => 'schema',
1648
                            'subject' => 'matview',
1649
                            'matview' => Decorator::field('matview'),
1650
                        ],
1651
                        'branch'  => true,
1652
                    ],
1653
                    'select'     => [
1654
                        'title'   => $lang['strselect'],
1655
                        'icon'    => 'Search',
1656
                        'url'     => 'materializedviews.php',
1657
                        'urlvars' => ['action' => 'confselectrows', 'matview' => Decorator::field('matview')],
1658
                        'help'    => 'pg.sql.select',
1659
                    ],
1660
                    'definition' => [
1661
                        'title'   => $lang['strdefinition'],
1662
                        'url'     => 'materializedviewproperties.php',
1663
                        'urlvars' => ['subject' => 'matview', 'matview' => Decorator::field('matview'), 'action' => 'definition'],
1664
                        'icon'    => 'Definition',
1665
                    ],
1666
                    'indexes'    => [
1667
                        'title'   => $lang['strindexes'],
1668
                        'url'     => 'indexes.php',
1669
                        'urlvars' => ['subject' => 'matview', 'matview' => Decorator::field('matview')],
1670
                        'help'    => 'pg.index',
1671
                        'icon'    => 'Indexes',
1672
                        'branch'  => true,
1673
                    ],
1674
                    /*'constraints' => [
1675
                    'title' => $lang['strconstraints'],
1676
                    'url' => 'constraints.php',
1677
                    'urlvars' => ['subject' => 'matview', 'matview' => Decorator::field('matview')],
1678
                    'help' => 'pg.constraint',
1679
                    'icon' => 'Constraints',
1680
                    'branch' => true,
1681
                     */
1682
1683
                    'rules'      => [
1684
                        'title'   => $lang['strrules'],
1685
                        'url'     => 'rules.php',
1686
                        'urlvars' => ['subject' => 'matview', 'matview' => Decorator::field('matview')],
1687
                        'help'    => 'pg.rule',
1688
                        'icon'    => 'Rules',
1689
                        'branch'  => true,
1690
                    ],
1691
                    'privileges' => [
1692
                        'title'   => $lang['strprivileges'],
1693
                        'url'     => 'privileges.php',
1694
                        'urlvars' => ['subject' => 'matview', 'matview' => Decorator::field('matview')],
1695
                        'help'    => 'pg.privilege',
1696
                        'icon'    => 'Privileges',
1697
                    ],
1698
                    'export'     => [
1699
                        'title'   => $lang['strexport'],
1700
                        'url'     => 'materializedviewproperties.php',
1701
                        'urlvars' => ['subject' => 'matview', 'matview' => Decorator::field('matview'), 'action' => 'export'],
1702
                        'icon'    => 'Export',
1703
                        'hide'    => false,
1704
                    ],
1705
                ];
1706
                break;
1707
1708 View Code Duplication
            case 'function':
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...
1709
                $tabs = [
1710
                    'definition' => [
1711
                        'title'   => $lang['strdefinition'],
1712
                        'url'     => 'functions.php',
1713
                        'urlvars' => [
1714
                            'subject'      => 'function',
1715
                            'function'     => Decorator::field('function'),
1716
                            'function_oid' => Decorator::field('function_oid'),
1717
                            'action'       => 'properties',
1718
                        ],
1719
                        'icon'    => 'Definition',
1720
                    ],
1721
                    'privileges' => [
1722
                        'title'   => $lang['strprivileges'],
1723
                        'url'     => 'privileges.php',
1724
                        'urlvars' => [
1725
                            'subject'      => 'function',
1726
                            'function'     => Decorator::field('function'),
1727
                            'function_oid' => Decorator::field('function_oid'),
1728
                        ],
1729
                        'icon'    => 'Privileges',
1730
                    ],
1731
                ];
1732
                break;
1733
1734 View Code Duplication
            case 'aggregate':
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...
1735
                $tabs = [
1736
                    'definition' => [
1737
                        'title'   => $lang['strdefinition'],
1738
                        'url'     => 'aggregates.php',
1739
                        'urlvars' => [
1740
                            'subject'  => 'aggregate',
1741
                            'aggrname' => Decorator::field('aggrname'),
1742
                            'aggrtype' => Decorator::field('aggrtype'),
1743
                            'action'   => 'properties',
1744
                        ],
1745
                        'icon'    => 'Definition',
1746
                    ],
1747
                ];
1748
                break;
1749
1750 View Code Duplication
            case 'role':
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...
1751
                $tabs = [
1752
                    'definition' => [
1753
                        'title'   => $lang['strdefinition'],
1754
                        'url'     => 'roles.php',
1755
                        'urlvars' => [
1756
                            'subject'  => 'role',
1757
                            'rolename' => Decorator::field('rolename'),
1758
                            'action'   => 'properties',
1759
                        ],
1760
                        'icon'    => 'Definition',
1761
                    ],
1762
                ];
1763
                break;
1764
1765
            case 'popup':
1766
                $tabs = [
1767
                    'sql'  => [
1768
                        'title'   => $lang['strsql'],
1769
                        'url'     => '/src/views/sqledit.php',
1770
                        'urlvars' => ['action' => 'sql', 'subject' => 'schema'],
1771
                        'help'    => 'pg.sql',
1772
                        'icon'    => 'SqlEditor',
1773
                    ],
1774
                    'find' => [
1775
                        'title'   => $lang['strfind'],
1776
                        'url'     => '/src/views/sqledit.php',
1777
                        'urlvars' => ['action' => 'find', 'subject' => 'schema'],
1778
                        'icon'    => 'Search',
1779
                    ],
1780
                ];
1781
                break;
1782
1783 View Code Duplication
            case 'column':
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...
1784
                $tabs = [
1785
                    'properties' => [
1786
                        'title'   => $lang['strcolprop'],
1787
                        'url'     => 'colproperties.php',
1788
                        'urlvars' => [
1789
                            'subject' => 'column',
1790
                            'table'   => Decorator::field('table'),
1791
                            'column'  => Decorator::field('column'),
1792
                        ],
1793
                        'icon'    => 'Column',
1794
                    ],
1795
                    'privileges' => [
1796
                        'title'   => $lang['strprivileges'],
1797
                        'url'     => 'privileges.php',
1798
                        'urlvars' => [
1799
                            'subject' => 'column',
1800
                            'table'   => Decorator::field('table'),
1801
                            'column'  => Decorator::field('column'),
1802
                        ],
1803
                        'help'    => 'pg.privilege',
1804
                        'icon'    => 'Privileges',
1805
                    ],
1806
                ];
1807
                break;
1808
1809
            case 'fulltext':
1810
                $tabs = [
1811
                    'ftsconfigs' => [
1812
                        'title'   => $lang['strftstabconfigs'],
1813
                        'url'     => 'fulltext.php',
1814
                        'urlvars' => ['subject' => 'schema'],
1815
                        'hide'    => !$data->hasFTS(),
1816
                        'help'    => 'pg.ftscfg',
1817
                        'tree'    => true,
1818
                        'icon'    => 'FtsCfg',
1819
                    ],
1820
                    'ftsdicts'   => [
1821
                        'title'   => $lang['strftstabdicts'],
1822
                        'url'     => 'fulltext.php',
1823
                        'urlvars' => ['subject' => 'schema', 'action' => 'viewdicts'],
1824
                        'hide'    => !$data->hasFTS(),
1825
                        'help'    => 'pg.ftsdict',
1826
                        'tree'    => true,
1827
                        'icon'    => 'FtsDict',
1828
                    ],
1829
                    'ftsparsers' => [
1830
                        'title'   => $lang['strftstabparsers'],
1831
                        'url'     => 'fulltext.php',
1832
                        'urlvars' => ['subject' => 'schema', 'action' => 'viewparsers'],
1833
                        'hide'    => !$data->hasFTS(),
1834
                        'help'    => 'pg.ftsparser',
1835
                        'tree'    => true,
1836
                        'icon'    => 'FtsParser',
1837
                    ],
1838
                ];
1839
                break;
1840
        }
1841
1842
        // Tabs hook's place
1843
        $plugin_functions_parameters = [
1844
            'tabs'    => &$tabs,
1845
            'section' => $section,
1846
        ];
1847
        $plugin_manager->do_hook('tabs', $plugin_functions_parameters);
1848
1849
        return $tabs;
1850
    }
1851
1852
    /**
1853
     * Get the URL for the last active tab of a particular tab bar.
1854
     *
1855
     * @param $section
1856
     *
1857
     * @return mixed|null
1858
     */
1859
    public function getLastTabURL($section)
1860
    {
1861
        $data = $this->getDatabaseAccessor();
1862
1863
        $tabs = $this->getNavTabs($section);
1864
1865 View Code Duplication
        if (isset($_SESSION['webdbLastTab'][$section]) && isset($tabs[$_SESSION['webdbLastTab'][$section]])) {
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...
1866
            $tab = $tabs[$_SESSION['webdbLastTab'][$section]];
1867
        } else {
1868
            $tab = reset($tabs);
1869
        }
1870
        $this->prtrace(['section' => $section, 'tabs' => $tabs, 'tab' => $tab]);
1871
1872
        return isset($tab['url']) ? $tab : null;
1873
    }
1874
1875
    /**
1876
     * Do multi-page navigation.  Displays the prev, next and page options.
1877
     *
1878
     * @param $page - the page currently viewed
1879
     * @param $pages - the maximum number of pages
1880
     * @param $gets -  the parameters to include in the link to the wanted page
1881
     * @param $max_width - the number of pages to make available at any one time (default = 20)
1882
     */
1883
    public function printPages($page, $pages, $gets, $max_width = 20)
1884
    {
1885
        $lang = $this->lang;
1886
1887
        $window = 10;
1888
1889
        if ($page < 0 || $page > $pages) {
1890
            return;
1891
        }
1892
1893
        if ($pages < 0) {
1894
            return;
1895
        }
1896
1897
        if ($max_width <= 0) {
1898
            return;
1899
        }
1900
1901
        unset($gets['page']);
1902
        $url = http_build_query($gets);
1903
1904
        if ($pages > 1) {
1905
            echo "<p style=\"text-align: center\">\n";
1906
            if ($page != 1) {
1907
                echo "<a class=\"pagenav\" href=\"?{$url}&amp;page=1\">{$lang['strfirst']}</a>\n";
1908
                $temp = $page - 1;
1909
                echo "<a class=\"pagenav\" href=\"?{$url}&amp;page={$temp}\">{$lang['strprev']}</a>\n";
1910
            }
1911
1912
            if ($page <= $window) {
1913
                $min_page = 1;
1914
                $max_page = min(2 * $window, $pages);
1915
            } elseif ($page > $window && $pages >= $page + $window) {
1916
                $min_page = ($page - $window) + 1;
1917
                $max_page = $page + $window;
1918
            } else {
1919
                $min_page = ($page - (2 * $window - ($pages - $page))) + 1;
1920
                $max_page = $pages;
1921
            }
1922
1923
            // Make sure min_page is always at least 1
1924
            // and max_page is never greater than $pages
1925
            $min_page = max($min_page, 1);
1926
            $max_page = min($max_page, $pages);
1927
1928
            for ($i = $min_page; $i <= $max_page; $i++) {
1929
                //if ($i != $page) echo "<a class=\"pagenav\" href=\"?{$url}&amp;page={$i}\">$i</a>\n";
1930
                if ($i != $page) {
1931
                    echo "<a class=\"pagenav\" href=\"display.php?{$url}&amp;page={$i}\">$i</a>\n";
1932
                } else {
1933
                    echo "$i\n";
1934
                }
1935
            }
1936
            if ($page != $pages) {
1937
                $temp = $page + 1;
1938
                echo "<a class=\"pagenav\" href=\"display.php?{$url}&amp;page={$temp}\">{$lang['strnext']}</a>\n";
1939
                echo "<a class=\"pagenav\" href=\"display.php?{$url}&amp;page={$pages}\">{$lang['strlast']}</a>\n";
1940
            }
1941
            echo "</p>\n";
1942
        }
1943
    }
1944
1945
    /**
1946
     * Converts a PHP.INI size variable to bytes.  Taken from publically available
1947
     * function by Chris DeRose, here: http://www.php.net/manual/en/configuration.directives.php#ini.file-uploads.
1948
     *
1949
     * @param $strIniSize The PHP.INI variable
1950
     *
1951
     * @return size in bytes, false on failure
1952
     */
1953
    public function inisizeToBytes($strIniSize)
1954
    {
1955
        // This function will take the string value of an ini 'size' parameter,
1956
        // and return a double (64-bit float) representing the number of bytes
1957
        // that the parameter represents. Or false if $strIniSize is unparseable.
1958
        $a_IniParts = [];
1959
1960
        if (!is_string($strIniSize)) {
1961
            return false;
1962
        }
1963
1964
        if (!preg_match('/^(\d+)([bkm]*)$/i', $strIniSize, $a_IniParts)) {
1965
            return false;
1966
        }
1967
1968
        $nSize = (float) $a_IniParts[1];
1969
        $strUnit = strtolower($a_IniParts[2]);
1970
1971
        switch ($strUnit) {
1972
            case 'm':
1973
                return $nSize * (float) 1048576;
1974
            case 'k':
1975
                return $nSize * (float) 1024;
1976
            case 'b':
1977
            default:
1978
                return $nSize;
1979
        }
1980
    }
1981
1982
    public function getRequestVars($subject = '')
1983
    {
1984
        $v = [];
1985
        if (!empty($subject)) {
1986
            $v['subject'] = $subject;
1987
        }
1988
1989
        if ($this->server_id !== null && $subject != 'root') {
1990
            $v['server'] = $this->server_id;
1991
            if ($this->database !== null && $subject != 'server') {
1992
                $v['database'] = $this->database;
1993
                if (isset($_REQUEST['schema']) && $subject != 'database') {
1994
                    $v['schema'] = $_REQUEST['schema'];
1995
                }
1996
            }
1997
        }
1998
        //$this->prtrace($v);
1999
        return $v;
2000
    }
2001
2002
    public function icon($icon)
2003
    {
2004
        if (is_string($icon)) {
2005
            $path = "/images/themes/{$this->conf['theme']}/{$icon}";
2006 View Code Duplication
            if (file_exists(BASE_PATH.$path.'.png')) {
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...
2007
                return SUBFOLDER.$path.'.png';
2008
            }
2009
2010 View Code Duplication
            if (file_exists(BASE_PATH.$path.'.gif')) {
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...
2011
                return SUBFOLDER.$path.'.gif';
2012
            }
2013
2014 View Code Duplication
            if (file_exists(BASE_PATH.$path.'.ico')) {
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...
2015
                return SUBFOLDER.$path.'.ico';
2016
            }
2017
2018
            $path = "/images/themes/default/{$icon}";
2019 View Code Duplication
            if (file_exists(BASE_PATH.$path.'.png')) {
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...
2020
                return SUBFOLDER.$path.'.png';
2021
            }
2022
2023 View Code Duplication
            if (file_exists(BASE_PATH.$path.'.gif')) {
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...
2024
                return SUBFOLDER.$path.'.gif';
2025
            }
2026
2027 View Code Duplication
            if (file_exists(BASE_PATH.$path.'.ico')) {
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...
2028
                return SUBFOLDER.$path.'.ico';
2029
            }
2030
        } else {
2031
            // Icon from plugins
2032
            $path = "/plugins/{$icon[0]}/images/{$icon[1]}";
2033 View Code Duplication
            if (file_exists(BASE_PATH.$path.'.png')) {
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...
2034
                return SUBFOLDER.$path.'.png';
2035
            }
2036
2037 View Code Duplication
            if (file_exists(BASE_PATH.$path.'.gif')) {
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...
2038
                return SUBFOLDER.$path.'.gif';
2039
            }
2040
2041 View Code Duplication
            if (file_exists(BASE_PATH.$path.'.ico')) {
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...
2042
                return SUBFOLDER.$path.'.ico';
2043
            }
2044
        }
2045
2046
        return '';
2047
    }
2048
2049
    /**
2050
     * Function to escape command line parameters.
2051
     *
2052
     * @param string $str The string to escape
2053
     *
2054
     * @return string The escaped string
2055
     */
2056
    public function escapeShellArg($str)
2057
    {
2058
        $data = $this->getDatabaseAccessor();
2059
        $lang = $this->lang;
2060
2061
        if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') {
2062
            // Due to annoying PHP bugs, shell arguments cannot be escaped
2063
            // (command simply fails), so we cannot allow complex objects
2064
            // to be dumped.
2065
            if (preg_match('/^[_.[:alnum:]]+$/', $str)) {
2066
                return $str;
2067
            }
2068
2069
            echo $lang['strcannotdumponwindows'];
2070
            exit;
2071
        } else {
2072
            return escapeshellarg($str);
2073
        }
2074
    }
2075
2076
    /**
2077
     * Function to escape command line programs.
2078
     *
2079
     * @param string $str The string to escape
2080
     *
2081
     * @return string The escaped string
2082
     */
2083
    public function escapeShellCmd($str)
2084
    {
2085
        $data = $this->getDatabaseAccessor();
2086
2087
        if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') {
2088
            $data->fieldClean($str);
2089
2090
            return '"'.$str.'"';
2091
        }
2092
2093
        return escapeshellcmd($str);
2094
    }
2095
2096
    /**
2097
     * Save the given SQL script in the history
2098
     * of the database and server.
2099
     *
2100
     * @param $script the SQL script to save.
2101
     */
2102
    public function saveScriptHistory($script)
2103
    {
2104
        list($usec, $sec) = explode(' ', microtime());
2105
        $time = ((float) $usec + (float) $sec);
2106
        $_SESSION['history'][$_REQUEST['server']][$_REQUEST['database']]["$time"] = [
2107
            'query'    => $script,
2108
            'paginate' => !isset($_REQUEST['paginate']) ? 'f' : 't',
2109
            'queryid'  => $time,
2110
        ];
2111
    }
2112
2113
    /*
2114
     * Output dropdown list to select server and
2115
     * databases form the popups windows.
2116
     * @param $onchange Javascript action to take when selections change.
2117
     */
2118
    public function printConnection($onchange, $do_print = true)
2119
    {
2120
        $lang = $this->lang;
2121
2122
        $connection_html = "<table class=\"printconnection\" style=\"width: 100%\"><tr><td class=\"popup_select1\">\n";
2123
2124
        $servers = $this->getServers();
2125
        $forcedserver = null;
2126
        if (count($servers) === 1) {
2127
            $forcedserver = $this->server_id;
2128
            $connection_html .= '<input type="hidden" readonly="readonly" value="'.$this->server_id.'" name="server">';
2129
        } else {
2130
            $connection_html .= '<label>';
2131
            $connection_html .= $this->printHelp($lang['strserver'], 'pg.server', false);
2132
            $connection_html .= ': </label>';
2133
            $connection_html .= " <select name=\"server\" {$onchange}>\n";
2134
            foreach ($servers as $info) {
2135
                if (empty($info['username'])) {
2136
                    continue;
2137
                }
2138
                $selected = isset($_REQUEST['server']) && $info['id'] == $_REQUEST['server'] ? ' selected="selected"' : '';
2139
                // not logged on this server
2140
                $connection_html .= '<option value="'.htmlspecialchars($info['id']).'" '.$selected.'>';
2141
                $connection_html .= htmlspecialchars("{$info['desc']} ({$info['id']})");
2142
                $connection_html .= "</option>\n";
2143
            }
2144
            $connection_html .= "</select>\n";
2145
        }
2146
2147
        $connection_html .= "</td><td class=\"popup_select2\" style=\"text-align: right\">\n";
2148
2149
        if (count($servers) === 1 && isset($servers[$this->server_id]['useonlydefaultdb']) && $servers[$this->server_id]['useonlydefaultdb'] === true) {
2150
            $connection_html .= '<input type="hidden" name="database" value="'.htmlspecialchars($servers[$this->server_id]['defaultdb'])."\" />\n";
2151
        } else {
2152
2153
            // Get the list of all databases
2154
            $data = $this->getDatabaseAccessor();
2155
            $databases = $data->getDatabases();
2156
            if ($databases->recordCount() > 0) {
2157
                $connection_html .= '<label>';
2158
                $connection_html .= $this->printHelp($lang['strdatabase'], 'pg.database', false);
2159
                $connection_html .= ": <select name=\"database\" {$onchange}>\n";
2160
2161
                //if no database was selected, user should select one
2162
                if (!isset($_REQUEST['database'])) {
2163
                    $connection_html .= "<option value=\"\">--</option>\n";
2164
                }
2165
2166
                while (!$databases->EOF) {
2167
                    $dbname = $databases->fields['datname'];
2168
                    $dbselected = isset($_REQUEST['database']) && $dbname == $_REQUEST['database'] ? ' selected="selected"' : '';
2169
                    $connection_html .= '<option value="'.htmlspecialchars($dbname).'" '.$dbselected.'>'.htmlspecialchars($dbname)."</option>\n";
2170
2171
                    $databases->moveNext();
2172
                }
2173
                $connection_html .= "</select></label>\n";
2174
            } else {
2175
                $server_info = $misc->getServerInfo();
2176
                $connection_html .= '<input type="hidden" name="database" value="'.htmlspecialchars($server_info['defaultdb'])."\" />\n";
2177
            }
2178
        }
2179
2180
        $connection_html .= "</td></tr></table>\n";
2181
2182
        if ($do_print) {
2183
            echo $connection_html;
2184
        } else {
2185
            return $connection_html;
2186
        }
2187
    }
2188
2189
    /**
2190
     * returns an array representing FKs definition for a table, sorted by fields
2191
     * or by constraint.
2192
     *
2193
     * @param $table The table to retrieve FK contraints from
2194
     * @returns the array of FK definition:
2195
     *   array(
2196
     *     'byconstr' => array(
2197
     *       constrain id => array(
2198
     *         confrelid => foreign relation oid
2199
     *         f_schema => foreign schema name
2200
     *         f_table => foreign table name
2201
     *         pattnums => array of parent's fields nums
2202
     *         pattnames => array of parent's fields names
2203
     *         fattnames => array of foreign attributes names
2204
     *       )
2205
     *     ),
2206
     *     'byfield' => array(
2207
     *       attribute num => array (constraint id, ...)
2208
     *     ),
2209
     *     'code' => HTML/js code to include in the page for auto-completion
2210
     *   )
2211
     **/
2212
    public function getAutocompleteFKProperties($table)
2213
    {
2214
        $data = $this->getDatabaseAccessor();
2215
2216
        $fksprops = [
2217
            'byconstr' => [],
2218
            'byfield'  => [],
2219
            'code'     => '',
2220
        ];
2221
2222
        $constrs = $data->getConstraintsWithFields($table);
2223
2224
        if (!$constrs->EOF) {
2225
            $conrelid = $constrs->fields['conrelid'];
2226
            while (!$constrs->EOF) {
2227
                if ($constrs->fields['contype'] == 'f') {
2228
                    if (!isset($fksprops['byconstr'][$constrs->fields['conid']])) {
2229
                        $fksprops['byconstr'][$constrs->fields['conid']] = [
2230
                            'confrelid' => $constrs->fields['confrelid'],
2231
                            'f_table'   => $constrs->fields['f_table'],
2232
                            'f_schema'  => $constrs->fields['f_schema'],
2233
                            'pattnums'  => [],
2234
                            'pattnames' => [],
2235
                            'fattnames' => [],
2236
                        ];
2237
                    }
2238
2239
                    $fksprops['byconstr'][$constrs->fields['conid']]['pattnums'][] = $constrs->fields['p_attnum'];
2240
                    $fksprops['byconstr'][$constrs->fields['conid']]['pattnames'][] = $constrs->fields['p_field'];
2241
                    $fksprops['byconstr'][$constrs->fields['conid']]['fattnames'][] = $constrs->fields['f_field'];
2242
2243
                    if (!isset($fksprops['byfield'][$constrs->fields['p_attnum']])) {
2244
                        $fksprops['byfield'][$constrs->fields['p_attnum']] = [];
2245
                    }
2246
2247
                    $fksprops['byfield'][$constrs->fields['p_attnum']][] = $constrs->fields['conid'];
2248
                }
2249
                $constrs->moveNext();
2250
            }
2251
2252
            $fksprops['code'] = "<script type=\"text/javascript\">\n";
2253
            $fksprops['code'] .= "var constrs = {};\n";
2254
            foreach ($fksprops['byconstr'] as $conid => $props) {
2255
                $fksprops['code'] .= "constrs.constr_{$conid} = {\n";
2256
                $fksprops['code'] .= 'pattnums: ['.implode(',', $props['pattnums'])."],\n";
2257
                $fksprops['code'] .= "f_table:'".addslashes(htmlentities($props['f_table'], ENT_QUOTES, 'UTF-8'))."',\n";
2258
                $fksprops['code'] .= "f_schema:'".addslashes(htmlentities($props['f_schema'], ENT_QUOTES, 'UTF-8'))."',\n";
2259
                $_ = '';
2260 View Code Duplication
                foreach ($props['pattnames'] as $n) {
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...
2261
                    $_ .= ",'".htmlentities($n, ENT_QUOTES, 'UTF-8')."'";
2262
                }
2263
                $fksprops['code'] .= 'pattnames: ['.substr($_, 1)."],\n";
2264
2265
                $_ = '';
2266 View Code Duplication
                foreach ($props['fattnames'] as $n) {
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...
2267
                    $_ .= ",'".htmlentities($n, ENT_QUOTES, 'UTF-8')."'";
2268
                }
2269
2270
                $fksprops['code'] .= 'fattnames: ['.substr($_, 1)."]\n";
2271
                $fksprops['code'] .= "};\n";
2272
            }
2273
2274
            $fksprops['code'] .= "var attrs = {};\n";
2275
            foreach ($fksprops['byfield'] as $attnum => $cstrs) {
2276
                $fksprops['code'] .= "attrs.attr_{$attnum} = [".implode(',', $fksprops['byfield'][$attnum])."];\n";
2277
            }
2278
2279
            $fksprops['code'] .= "var table='".addslashes(htmlentities($table, ENT_QUOTES, 'UTF-8'))."';";
2280
            $fksprops['code'] .= "var server='".htmlentities($_REQUEST['server'], ENT_QUOTES, 'UTF-8')."';";
2281
            $fksprops['code'] .= "var database='".addslashes(htmlentities($_REQUEST['database'], ENT_QUOTES, 'UTF-8'))."';";
2282
            $fksprops['code'] .= "var subfolder='".SUBFOLDER."';";
2283
            $fksprops['code'] .= "</script>\n";
2284
2285
            $fksprops['code'] .= '<div id="fkbg"></div>';
2286
            $fksprops['code'] .= '<div id="fklist"></div>';
2287
            $fksprops['code'] .= '<script src="'.SUBFOLDER.'/js/ac_insert_row.js" type="text/javascript"></script>';
2288
        } else /* we have no foreign keys on this table */
2289
        {
2290
            return false;
2291
        }
2292
2293
        return $fksprops;
2294
    }
2295
}
2296