HTMLNavbarController   D
last analyzed

Complexity

Total Complexity 59

Size/Duplication

Total Lines 536
Duplicated Lines 0 %

Importance

Changes 13
Bugs 0 Features 1
Metric Value
eloc 290
c 13
b 0
f 1
dl 0
loc 536
rs 4.08
wmc 59

10 Methods

Rating   Name   Duplication   Size   Complexity  
C _getLastTrailPart() 0 74 11
B _getCrumbs() 0 28 7
A getLastTabURL() 0 14 3
C printTabs() 0 54 14
A getHREFSubject() 0 6 1
B printTopbar() 0 110 6
A _getSearchPathsCrumbs() 0 26 3
A printTrail() 0 33 4
B _getTrail() 0 105 7
A _getTrailsFromArray() 0 17 3

How to fix   Complexity   

Complex Class

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

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

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

1
<?php
2
3
/**
4
 * PHPPgAdmin 6.1.3
5
 */
6
7
namespace PHPPgAdmin\XHtml;
8
9
/**
10
 * Class to render tables. Formerly part of Misc.php.
11
 */
12
class HTMLNavbarController extends HTMLController
13
{
14
    public $controller_name = 'HTMLNavbarController';
15
16
    /**
17
     * Display a bread crumb trail.
18
     *
19
     * @param array|string $trail    an array of breadcrumb items, or a string to identify one of them
20
     * @param bool         $do_print true  to echo, false to return html
21
     * @param null|string  $from
22
     *
23
     * @return string ( description_of_the_return_value )
24
     */
25
    public function printTrail($trail = [], $do_print = true, $from = null)
26
    {
27
        $from = $from ? $from : __METHOD__;
28
29
        $trail_html = $this->printTopbar(false, $from);
30
31
        if (\is_string($trail)) {
32
            $subject = $trail;
33
            $trail = $this->_getTrail($subject);
34
            // Trail hook's place
35
            $plugin_functions_parameters = [
0 ignored issues
show
Unused Code introduced by
The assignment to $plugin_functions_parameters is dead and can be removed.
Loading history...
36
                'trail' => &$trail,
37
                'section' => $subject,
38
            ];
39
        }
40
41
        $crumbs = $this->_getCrumbs($trail);
42
43
        $viewVars = [
44
            'crumbs' => $crumbs,
45
            'controller_name' => $this->controller_name,
46
        ];
47
        $viewVars = $this->_getSearchPathsCrumbs($crumbs, $viewVars);
48
49
        $trail_html .= $this->getContainer()->view->fetch('components/trail.twig', $viewVars);
50
51
        if ($do_print) {
52
            echo $trail_html;
53
54
            return '';
55
        }
56
57
        return $trail_html;
58
    }
59
60
    /**
61
     * Get the URL for the last active tab of a particular tab bar.
62
     *
63
     * @param string $section
64
     *
65
     * @return null|mixed
66
     */
67
    public function getLastTabURL($section)
68
    {
69
        //$data = $this->getDatabaseAccessor();
70
71
        $tabs = $this->misc->getNavTabs($section);
72
73
        if (isset($_SESSION['webdbLastTab'][$section], $tabs[$_SESSION['webdbLastTab'][$section]])) {
74
            $tab = $tabs[$_SESSION['webdbLastTab'][$section]];
75
        } else {
76
            $tab = \reset($tabs);
77
        }
78
        // $this->prtrace(['section' => $section, 'tabs' => $tabs, 'tab' => $tab]);
79
80
        return isset($tab['url']) ? $tab : null;
81
    }
82
83
    /**
84
     * Display navigation tabs.
85
     *
86
     * @param string      $alltabs   The name of current section (Ex: intro, server, ...),
87
     *                               or an array with tabs (Ex: sqledit::doFind function)
88
     * @param string      $activetab the name of the tab to be highlighted
89
     * @param bool        $do_print  true to print html, false to return html
90
     * @param null|string $from      whichi method is calling this one
91
     */
92
    public function printTabs($alltabs, $activetab, $do_print = true, $from = null)
93
    {
94
        $from = $from ? $from : __METHOD__;
95
96
        $this->misc = $this->misc;
97
        $_SESSION['webdbLastTab'] = $_SESSION['webdbLastTab'] ?? [];
98
99
        if (!\is_array($_SESSION['webdbLastTab'])) {
100
            $_SESSION['webdbLastTab'] = [$alltabs => $activetab];
101
        }
102
103
        if (\is_string($alltabs)) {
0 ignored issues
show
introduced by
The condition is_string($alltabs) is always true.
Loading history...
104
            $_SESSION['webdbLastTab'][$alltabs] = $activetab;
105
            $alltabs = $this->misc->getNavTabs($alltabs);
106
        }
107
        $tabs_html = '';
108
109
        //Getting only visible tabs
110
        $tabs = [];
111
112
        if (0 < \count($alltabs)) {
113
            foreach ($alltabs as $tab_id => $tab) {
114
                if (!isset($tab['hide']) || true !== $tab['hide']) {
115
                    $tabs[$tab_id] = $tab;
116
                    $tabs[$tab_id]['active'] = ($tab_id === $activetab) ? ' active' : '';
117
                    $tabs[$tab_id]['tablink'] = \str_replace(['&amp;', '.php'], ['&', ''], \htmlentities($this->getActionUrl($tab, $_REQUEST, $from)));
118
119
                    if (isset($tab['icon']) && $icon = $this->view->icon($tab['icon'])) {
120
                        $tabs[$tab_id]['iconurl'] = $icon;
121
                    }
122
123
                    if (isset($tab['help'])) {
124
                        $tabs[$tab_id]['helpurl'] = \str_replace('&amp;', '&', $this->view->getHelpLink($tab['help']));
125
                    }
126
                }
127
            }
128
        }
129
130
        if (0 < \count($tabs)) {
131
            $width = (int) (100 / \count($tabs)) . '%';
132
133
            $viewVars = [
134
                'width' => $width,
135
                'tabs' => $tabs,
136
                'controller_name' => $this->controller_name,
137
            ];
138
139
            $tabs_html = $this->getContainer()->view->fetch('components/tabs.twig', $viewVars);
140
        }
141
142
        if ($do_print) {
143
            echo $tabs_html;
144
        } else {
145
            return $tabs_html;
146
        }
147
    }
148
149
    private function _getCrumbs($trail)
150
    {
151
        $crumbs = [];
152
153
        foreach ($trail as $crumb_id => $crumb) {
154
            if (isset($crumb['url'])) {
155
                $crumbs[$crumb_id]['url'] = \str_replace('&amp;', '&', $crumb['url']);
156
            }
157
158
            if (isset($crumb['title'])) {
159
                $crumbs[$crumb_id]['title'] = $crumb['title'];
160
                $crumbs[$crumb_id]['iconalt'] = $crumb['title'];
161
            } else {
162
                $crumbs[$crumb_id]['iconalt'] = 'Database Root';
163
            }
164
165
            if (isset($crumb['icon']) && $icon = $this->view->icon($crumb['icon'])) {
166
                $crumbs[$crumb_id]['icon'] = $icon;
167
            }
168
169
            $crumbs[$crumb_id]['text'] = $crumb['text'];
170
171
            if (isset($crumb['help'])) {
172
                $crumbs[$crumb_id]['helpurl'] = \str_replace('&amp;', '&', $this->view->getHelpLink($crumb['help']));
173
            }
174
        }
175
176
        return $crumbs;
177
    }
178
179
    /**
180
     * @param mixed $crumbs
181
     * @param array $viewVars
182
     */
183
    private function _getSearchPathsCrumbs($crumbs, array $viewVars)
184
    {
185
        $data = $this->misc->getDatabaseAccessor();
186
        $lang = $this->lang;
187
188
        if (isset($crumbs['database'])) {
189
            $search_path_crumbs = [];
190
            $dburl = $crumbs['database']['url'];
191
            $search_paths = $data->getSearchPath();
192
193
            foreach ($search_paths as $schema) {
194
                $url = \str_replace(['&amp;', 'redirect/database'], ['&', 'redirect/schema'], $dburl . '&schema=' . $schema);
195
                $destination = $this->container->getDestinationWithLastTab('database');
0 ignored issues
show
Unused Code introduced by
The assignment to $destination is dead and can be removed.
Loading history...
196
                //$this->dump(['url' => $url, 'destination' => $destination]);
197
                $search_path_crumbs[$schema] = [
198
                    'title' => $lang['strschema'],
199
                    'text' => $schema,
200
                    'icon' => $this->view->icon('Schema'),
201
                    'iconalt' => $lang['strschema'],
202
                    'url' => $url,
203
                ];
204
            }
205
            $viewVars['search_paths'] = $search_path_crumbs;
206
        }
207
208
        return $viewVars;
209
    }
210
211
    /**
212
     * [printTopbar description].
213
     *
214
     * @param bool       $do_print true to print, false to return html
215
     * @param null|mixed $from     which method is calling this one
216
     */
217
    private function printTopbar($do_print = true, $from = null): ?string
218
    {
219
        $from = $from ? $from : __METHOD__;
220
221
        $lang = $this->lang;
222
223
        $this->misc = $this->misc;
224
        $appName = $this->misc->appName;
225
        $appVersion = $this->misc->appVersion;
226
227
        $server_info = $this->misc->getServerInfo();
228
        $server_id = $this->misc->getServerId();
229
        $reqvars = $this->misc->getRequestVars('table');
230
231
        $topbar_html = '<div class="topbar" data-controller="' . $this->controller_name . '"><table style="width: 100%"><tr><td>';
232
233
        if ($server_info && isset($server_info['platform'], $server_info['username'])) {
234
            // top left informations when connected
235
            $topbar_html .= \sprintf(
236
                $lang['strtopbar'],
237
                '<span class="platform">' . \htmlspecialchars($server_info['platform']) . '</span>',
238
                '<span class="host">' . \htmlspecialchars((empty($server_info['host'])) ? 'localhost' : $server_info['host']) . '</span>',
239
                '<span class="port">' . \htmlspecialchars($server_info['port']) . '</span>',
240
                '<span class="username">' . \htmlspecialchars($server_info['username']) . '</span>'
241
            );
242
243
            $topbar_html .= '</td>';
244
245
            // top right informations when connected
246
247
            $toplinks = [
248
                'sql' => [
249
                    'attr' => [
250
                        'href' => [
251
                            'url' => \containerInstance()->subFolder . '/src/views/sqledit',
252
                            'urlvars' => \array_merge($reqvars, [
253
                                'action' => 'sql',
254
                            ]),
255
                        ],
256
                        'target' => 'sqledit',
257
                        'id' => 'toplink_sql',
258
                        'class' => 'toplink_popup',
259
                    ],
260
                    'content' => $lang['strsql'],
261
                ],
262
                'history' => [
263
                    'attr' => [
264
                        'href' => [
265
                            'url' => \containerInstance()->subFolder . '/src/views/history',
266
                            'urlvars' => \array_merge($reqvars, [
267
                                'action' => 'pophistory',
268
                            ]),
269
                        ],
270
                        'id' => 'toplink_history',
271
                        'class' => 'toplink_popup',
272
                    ],
273
                    'content' => $lang['strhistory'],
274
                ],
275
                'find' => [
276
                    'attr' => [
277
                        'href' => [
278
                            'url' => \containerInstance()->subFolder . '/src/views/sqledit',
279
                            'urlvars' => \array_merge($reqvars, [
280
                                'action' => 'find',
281
                            ]),
282
                        ],
283
                        'target' => 'sqledit',
284
                        'id' => 'toplink_find',
285
                        'class' => 'toplink_popup',
286
                    ],
287
                    'content' => $lang['strfind'],
288
                ],
289
                'logout' => [
290
                    'attr' => [
291
                        'href' => [
292
                            'url' => \containerInstance()->subFolder . '/src/views/servers',
293
                            'urlvars' => [
294
                                'action' => 'logout',
295
                                'logoutServer' => \sha1("{$server_info['host']}:{$server_info['port']}:{$server_info['sslmode']}"),
296
                            ],
297
                        ],
298
                        'id' => 'toplink_logout',
299
                    ],
300
                    'content' => $lang['strlogout'],
301
                ],
302
            ];
303
304
            // Toplink hook's place
305
            $plugin_functions_parameters = [
0 ignored issues
show
Unused Code introduced by
The assignment to $plugin_functions_parameters is dead and can be removed.
Loading history...
306
                'toplinks' => &$toplinks,
307
            ];
308
309
            $topbar_html .= '<td style="text-align: right">';
310
311
            $topbar_html .= $this->printLinksList($toplinks, 'toplink', false, $from);
312
313
            $topbar_html .= '</td>';
314
        } else {
315
            $topbar_html .= "<span class=\"appname\">{$appName}</span> <span class=\"version\">{$appVersion}</span>";
316
        }
317
318
        $topbar_html .= '</tr></table></div>' . \PHP_EOL;
319
320
        if ($do_print) {
321
            echo $topbar_html;
322
323
            return '';
324
        }
325
326
        return $topbar_html;
327
    }
328
329
    private function getHREFSubject(string $subject)
330
    {
331
        $vars = $this->misc->getSubjectParams($subject);
332
        \ksort($vars['params']);
333
334
        return "{$vars['url']}?" . \http_build_query($vars['params'], '', '&amp;');
335
    }
336
337
    /**
338
     * Create a bread crumb trail of the object hierarchy.
339
     *
340
     * @param null|string $subject sunkect of the trail
341
     *
342
     * @return array the trail array
343
     */
344
    private function _getTrail($subject = null)
345
    {
346
        $lang = $this->lang;
347
348
        $appName = $this->misc->appName;
349
350
        $trail = [];
351
352
        $trail['root'] = [
353
            'text' => $appName,
354
            'url' => \containerInstance()->subFolder . '/src/views/servers',
355
            'icon' => 'Introduction',
356
        ];
357
358
        if ('root' === $subject) {
359
            return $trail;
360
        }
361
362
        $server_info = $this->misc->getServerInfo();
363
        $trail['server'] = [
364
            'title' => $lang['strserver'],
365
            'text' => $server_info['desc'],
366
            'url' => $this->getHREFSubject('server'),
367
            'help' => 'pg.server',
368
            'icon' => 'Server',
369
        ];
370
371
        if ('server' === $subject) {
372
            return $trail;
373
        }
374
375
        $database_rolename = [
376
            'database' => [
377
                'title' => $lang['strdatabase'],
378
                'subject' => 'database',
379
                'help' => 'pg.database',
380
                'icon' => 'Database',
381
            ],
382
            'rolename' => [
383
                'title' => $lang['strrole'],
384
                'subject' => 'role',
385
                'help' => 'pg.role',
386
                'icon' => 'Roles',
387
            ],
388
        ];
389
390
        $trail = $this->_getTrailsFromArray($trail, $database_rolename);
391
392
        if (\in_array($subject, ['database', 'role'], true)) {
393
            return $trail;
394
        }
395
396
        $schema = [
397
            'schema' => [
398
                'title' => $lang['strschema'],
399
                'subject' => 'schema',
400
                'help' => 'pg.schema',
401
                'icon' => 'Schema',
402
            ],
403
        ];
404
405
        $trail = $this->_getTrailsFromArray($trail, $schema);
406
407
        if ('schema' === $subject) {
408
            return $trail;
409
        }
410
411
        $table_view_matview_fts = [
412
            'table' => [
413
                'title' => $lang['strtable'],
414
                'subject' => 'table',
415
                'help' => 'pg.table',
416
                'icon' => 'Table',
417
            ],
418
            'view' => [
419
                'title' => $lang['strview'],
420
                'subject' => 'view',
421
                'help' => 'pg.view',
422
                'icon' => 'View',
423
            ],
424
            'matview' => [
425
                'title' => 'M' . $lang['strview'],
426
                'subject' => 'matview',
427
                'help' => 'pg.matview',
428
                'icon' => 'MViews',
429
            ],
430
            'ftscfg' => [
431
                'title' => $lang['strftsconfig'],
432
                'subject' => 'ftscfg',
433
                'help' => 'pg.ftscfg.example',
434
                'icon' => 'Fts',
435
            ],
436
        ];
437
438
        $trail = $this->_getTrailsFromArray($trail, $table_view_matview_fts);
439
440
        if (\in_array($subject, ['table', 'view', 'matview', 'ftscfg'], true)) {
441
            return $trail;
442
        }
443
444
        if (null !== $subject) {
445
            $trail = $this->_getLastTrailPart($subject, $trail);
446
        }
447
448
        return $trail;
449
    }
450
451
    /**
452
     * @param (mixed|string)[][] $trail
453
     * @param (mixed|string)[][] $the_array
454
     */
455
    private function _getTrailsFromArray(array $trail, array $the_array)
456
    {
457
        foreach ($the_array as $key => $value) {
458
            if (isset($_REQUEST[$key])) {
459
                $trail[$key] = [
460
                    'title' => $value['title'],
461
                    'text' => $_REQUEST[$key],
462
                    'url' => $this->getHREFSubject($value['subject']),
463
                    'help' => $value['help'],
464
                    'icon' => $value['icon'],
465
                ];
466
467
                break;
468
            }
469
        }
470
471
        return $trail;
472
    }
473
474
    private function _getLastTrailPart(string $subject, $trail)
475
    {
476
        $lang = $this->lang;
477
478
        switch ($subject) {
479
            case 'function':
480
                $trail[$subject] = [
481
                    'title' => $lang['str' . $subject],
482
                    'text' => $_REQUEST[$subject],
483
                    'url' => $this->getHREFSubject('function'),
484
                    'help' => 'pg.function',
485
                    'icon' => 'Function',
486
                ];
487
488
                break;
489
            case 'aggregate':
490
                $trail[$subject] = [
491
                    'title' => $lang['straggregate'],
492
                    'text' => $_REQUEST['aggrname'],
493
                    'url' => $this->getHREFSubject('aggregate'),
494
                    'help' => 'pg.aggregate',
495
                    'icon' => 'Aggregate',
496
                ];
497
498
                break;
499
            case 'column':
500
                $trail['column'] = [
501
                    'title' => $lang['strcolumn'],
502
                    'text' => $_REQUEST['column'],
503
                    'icon' => 'Column',
504
                    'url' => $this->getHREFSubject('column'),
505
                ];
506
507
                break;
508
509
            default:
510
                if (isset($_REQUEST[$subject])) {
511
                    switch ($subject) {
512
                        case 'domain':
513
                            $icon = 'Domain';
514
515
                            break;
516
                        case 'sequence':
517
                            $icon = 'Sequence';
518
519
                            break;
520
                        case 'type':
521
                            $icon = 'Type';
522
523
                            break;
524
                        case 'operator':
525
                            $icon = 'Operator';
526
527
                            break;
528
                        case 'index':
529
                            $icon = 'Index';
530
531
                            break;
532
533
                        default:
534
                            $icon = null;
535
536
                            break;
537
                    }
538
                    $trail[$subject] = [
539
                        'title' => \array_key_exists('str' . $subject, $lang) ? $lang['str' . $subject] : $subject,
540
                        'text' => $_REQUEST[$subject],
541
                        'help' => 'pg.' . $subject,
542
                        'icon' => $icon,
543
                    ];
544
                }
545
        }
546
547
        return $trail;
548
    }
549
}
550