Translated using Weblate (Slovenian)
[phpmyadmin.git] / libraries / classes / Menu.php
blob17e8acf65482b94622486c1d203e0c5474b05a6a
1 <?php
2 /**
3 * Generates and renders the top menu
4 */
6 declare(strict_types=1);
8 namespace PhpMyAdmin;
10 use PhpMyAdmin\Query\Utilities;
11 use PhpMyAdmin\Utils\SessionCache;
12 use function array_key_exists;
13 use function count;
14 use function in_array;
15 use function mb_strpos;
16 use function mb_strstr;
17 use function mb_substr;
18 use function md5;
19 use function preg_replace;
20 use function strlen;
21 use function substr;
23 /**
24 * Class for generating the top menu
26 class Menu
28 /**
29 * Database name
31 * @access private
32 * @var string
34 private $db;
35 /**
36 * Table name
38 * @access private
39 * @var string
41 private $table;
43 /** @var Relation */
44 private $relation;
46 /** @var Template */
47 private $template;
49 /**
50 * Creates a new instance of Menu
52 * @param string $db Database name
53 * @param string $table Table name
55 public function __construct($db, $table)
57 global $dbi;
59 $this->db = $db;
60 $this->table = $table;
61 $this->relation = new Relation($dbi);
62 $this->template = new Template();
65 /**
66 * Returns the menu and the breadcrumbs as a string
68 * @return string
70 public function getDisplay()
72 $retval = $this->getBreadcrumbs();
73 $retval .= $this->getMenu();
75 return $retval;
78 /**
79 * Returns hash for the menu and the breadcrumbs
81 * @return string
83 public function getHash()
85 return substr(
86 md5($this->getMenu() . $this->getBreadcrumbs()),
92 /**
93 * Returns the menu as HTML
95 * @return string HTML formatted menubar
97 private function getMenu(): string
99 $url_params = [];
101 if (strlen((string) $this->table) > 0) {
102 $tabs = $this->getTableTabs();
103 $url_params['db'] = $this->db;
104 $url_params['table'] = $this->table;
105 $level = 'table';
106 } elseif (strlen($this->db) > 0) {
107 $tabs = $this->getDbTabs();
108 $url_params['db'] = $this->db;
109 $level = 'db';
110 } else {
111 $tabs = $this->getServerTabs();
112 $level = 'server';
115 $allowedTabs = $this->getAllowedTabs($level);
116 foreach ($tabs as $key => $value) {
117 if (array_key_exists($key, $allowedTabs)) {
118 continue;
121 unset($tabs[$key]);
124 return $this->template->render('top_menu', [
125 'tabs' => $tabs,
126 'url_params' => $url_params,
131 * Returns a list of allowed tabs for the current user for the given level
133 * @param string $level 'server', 'db' or 'table' level
135 * @return array list of allowed tabs
137 private function getAllowedTabs($level)
139 /** @var DatabaseInterface $dbi */
140 global $dbi;
142 $cache_key = 'menu-levels-' . $level;
143 if (SessionCache::has($cache_key)) {
144 return SessionCache::get($cache_key);
146 $allowedTabs = Util::getMenuTabList($level);
147 $cfgRelation = $this->relation->getRelationsParam();
148 if ($cfgRelation['menuswork']) {
149 $groupTable = Util::backquote($cfgRelation['db'])
150 . '.'
151 . Util::backquote($cfgRelation['usergroups']);
152 $userTable = Util::backquote($cfgRelation['db'])
153 . '.' . Util::backquote($cfgRelation['users']);
155 $sql_query = 'SELECT `tab` FROM ' . $groupTable
156 . " WHERE `allowed` = 'N'"
157 . " AND `tab` LIKE '" . $level . "%'"
158 . ' AND `usergroup` = (SELECT usergroup FROM '
159 . $userTable . " WHERE `username` = '"
160 . $dbi->escapeString($GLOBALS['cfg']['Server']['user']) . "')";
162 $result = $this->relation->queryAsControlUser($sql_query, false);
163 if ($result) {
164 while ($row = $dbi->fetchAssoc($result)) {
165 $tabName = mb_substr(
166 $row['tab'],
167 mb_strpos($row['tab'], '_') + 1
169 unset($allowedTabs[$tabName]);
173 SessionCache::set($cache_key, $allowedTabs);
175 return $allowedTabs;
179 * Returns the breadcrumbs as HTML
181 * @return string HTML formatted breadcrumbs
183 private function getBreadcrumbs(): string
185 global $cfg, $dbi;
187 $server = [];
188 $database = [];
189 $table = [];
191 if (empty($cfg['Server']['host'])) {
192 $cfg['Server']['host'] = '';
194 $server['name'] = ! empty($cfg['Server']['verbose'])
195 ? $cfg['Server']['verbose'] : $cfg['Server']['host'];
196 $server['name'] .= empty($cfg['Server']['port'])
197 ? '' : ':' . $cfg['Server']['port'];
198 $server['url'] = Util::getScriptNameForOption(
199 $cfg['DefaultTabServer'],
200 'server'
203 if (strlen($this->db) > 0) {
204 $database['name'] = $this->db;
205 $database['url'] = Util::getScriptNameForOption(
206 $cfg['DefaultTabDatabase'],
207 'database'
209 if (strlen((string) $this->table) > 0) {
210 $table['name'] = $this->table;
211 $table['url'] = Util::getScriptNameForOption(
212 $cfg['DefaultTabTable'],
213 'table'
215 /** @var Table $tableObj */
216 $tableObj = $dbi->getTable($this->db, $this->table);
217 $table['is_view'] = $tableObj->isView();
218 $table['comment'] = '';
219 if (! $table['is_view']) {
220 $table['comment'] = $tableObj->getComment();
222 if (mb_strstr($table['comment'], '; InnoDB free')) {
223 $table['comment'] = preg_replace(
224 '@; InnoDB free:.*?$@',
226 $table['comment']
229 } else {
230 // no table selected, display database comment if present
231 $cfgRelation = $this->relation->getRelationsParam();
233 // Get additional information about tables for tooltip is done
234 // in Util::getDbInfo() only once
235 if ($cfgRelation['commwork']) {
236 $database['comment'] = $this->relation->getDbComment($this->db);
241 return $this->template->render('menu/breadcrumbs', [
242 'server' => $server,
243 'database' => $database,
244 'table' => $table,
249 * Returns the table tabs as an array
251 * @return array Data for generating table tabs
253 private function getTableTabs()
255 /** @var DatabaseInterface $dbi */
256 global $route, $dbi;
258 $isSystemSchema = Utilities::isSystemSchema($this->db);
259 $tbl_is_view = $dbi->getTable($this->db, $this->table)
260 ->isView();
261 $updatable_view = false;
262 if ($tbl_is_view) {
263 $updatable_view = $dbi->getTable($this->db, $this->table)
264 ->isUpdatableView();
266 $is_superuser = $dbi->isSuperUser();
267 $isCreateOrGrantUser = $dbi->isGrantUser() || $dbi->isCreateUser();
269 $tabs = [];
271 $tabs['browse']['icon'] = 'b_browse';
272 $tabs['browse']['text'] = __('Browse');
273 $tabs['browse']['route'] = '/sql';
274 $tabs['browse']['args']['pos'] = 0;
275 $tabs['browse']['active'] = $route === '/sql';
277 $tabs['structure']['icon'] = 'b_props';
278 $tabs['structure']['route'] = '/table/structure';
279 $tabs['structure']['text'] = __('Structure');
280 $tabs['structure']['active'] = in_array($route, [
281 '/table/relation',
282 '/table/structure',
285 $tabs['sql']['icon'] = 'b_sql';
286 $tabs['sql']['route'] = '/table/sql';
287 $tabs['sql']['text'] = __('SQL');
288 $tabs['sql']['active'] = $route === '/table/sql';
290 $tabs['search']['icon'] = 'b_search';
291 $tabs['search']['text'] = __('Search');
292 $tabs['search']['route'] = '/table/search';
293 $tabs['search']['active'] = in_array($route, [
294 '/table/find-replace',
295 '/table/search',
296 '/table/zoom-search',
299 if (! $isSystemSchema && (! $tbl_is_view || $updatable_view)) {
300 $tabs['insert']['icon'] = 'b_insrow';
301 $tabs['insert']['route'] = '/table/change';
302 $tabs['insert']['text'] = __('Insert');
303 $tabs['insert']['active'] = $route === '/table/change';
306 $tabs['export']['icon'] = 'b_tblexport';
307 $tabs['export']['route'] = '/table/export';
308 $tabs['export']['args']['single_table'] = 'true';
309 $tabs['export']['text'] = __('Export');
310 $tabs['export']['active'] = $route === '/table/export';
313 * Don't display "Import" for views and information_schema
315 if (! $tbl_is_view && ! $isSystemSchema) {
316 $tabs['import']['icon'] = 'b_tblimport';
317 $tabs['import']['route'] = '/table/import';
318 $tabs['import']['text'] = __('Import');
319 $tabs['import']['active'] = $route === '/table/import';
321 if (($is_superuser || $isCreateOrGrantUser)
322 && ! $isSystemSchema
324 $tabs['privileges']['route'] = '/server/privileges';
325 $tabs['privileges']['args']['checkprivsdb'] = $this->db;
326 $tabs['privileges']['args']['checkprivstable'] = $this->table;
327 // stay on table view
328 $tabs['privileges']['args']['viewing_mode'] = 'table';
329 $tabs['privileges']['text'] = __('Privileges');
330 $tabs['privileges']['icon'] = 's_rights';
331 $tabs['privileges']['active'] = $route === '/server/privileges';
334 * Don't display "Operations" for views and information_schema
336 if (! $tbl_is_view && ! $isSystemSchema) {
337 $tabs['operation']['icon'] = 'b_tblops';
338 $tabs['operation']['route'] = '/table/operations';
339 $tabs['operation']['text'] = __('Operations');
340 $tabs['operation']['active'] = $route === '/table/operations';
343 * Views support a limited number of operations
345 if ($tbl_is_view && ! $isSystemSchema) {
346 $tabs['operation']['icon'] = 'b_tblops';
347 $tabs['operation']['route'] = '/view/operations';
348 $tabs['operation']['text'] = __('Operations');
349 $tabs['operation']['active'] = $route === '/view/operations';
352 if (Tracker::isActive() && ! $isSystemSchema) {
353 $tabs['tracking']['icon'] = 'eye';
354 $tabs['tracking']['text'] = __('Tracking');
355 $tabs['tracking']['route'] = '/table/tracking';
356 $tabs['tracking']['active'] = $route === '/table/tracking';
358 if (! $isSystemSchema
359 && Util::currentUserHasPrivilege(
360 'TRIGGER',
361 $this->db,
362 $this->table
364 && ! $tbl_is_view
366 $tabs['triggers']['route'] = '/table/triggers';
367 $tabs['triggers']['text'] = __('Triggers');
368 $tabs['triggers']['icon'] = 'b_triggers';
369 $tabs['triggers']['active'] = $route === '/table/triggers';
372 return $tabs;
376 * Returns the db tabs as an array
378 * @return array Data for generating db tabs
380 private function getDbTabs()
382 /** @var DatabaseInterface $dbi */
383 global $route, $dbi;
385 $isSystemSchema = Utilities::isSystemSchema($this->db);
386 $num_tables = count($dbi->getTables($this->db));
387 $is_superuser = $dbi->isSuperUser();
388 $isCreateOrGrantUser = $dbi->isGrantUser() || $dbi->isCreateUser();
391 * Gets the relation settings
393 $cfgRelation = $this->relation->getRelationsParam();
395 $tabs = [];
397 $tabs['structure']['route'] = '/database/structure';
398 $tabs['structure']['text'] = __('Structure');
399 $tabs['structure']['icon'] = 'b_props';
400 $tabs['structure']['active'] = $route === '/database/structure';
402 $tabs['sql']['route'] = '/database/sql';
403 $tabs['sql']['text'] = __('SQL');
404 $tabs['sql']['icon'] = 'b_sql';
405 $tabs['sql']['active'] = $route === '/database/sql';
407 $tabs['search']['text'] = __('Search');
408 $tabs['search']['icon'] = 'b_search';
409 $tabs['search']['route'] = '/database/search';
410 $tabs['search']['active'] = $route === '/database/search';
411 if ($num_tables == 0) {
412 $tabs['search']['warning'] = __('Database seems to be empty!');
415 $tabs['query']['text'] = __('Query');
416 $tabs['query']['icon'] = 's_db';
417 $tabs['query']['route'] = '/database/multi-table-query';
418 $tabs['query']['active'] = $route === '/database/multi-table-query' || $route === '/database/qbe';
419 if ($num_tables == 0) {
420 $tabs['query']['warning'] = __('Database seems to be empty!');
423 $tabs['export']['text'] = __('Export');
424 $tabs['export']['icon'] = 'b_export';
425 $tabs['export']['route'] = '/database/export';
426 $tabs['export']['active'] = $route === '/database/export';
427 if ($num_tables == 0) {
428 $tabs['export']['warning'] = __('Database seems to be empty!');
431 if (! $isSystemSchema) {
432 $tabs['import']['route'] = '/database/import';
433 $tabs['import']['text'] = __('Import');
434 $tabs['import']['icon'] = 'b_import';
435 $tabs['import']['active'] = $route === '/database/import';
437 $tabs['operation']['route'] = '/database/operations';
438 $tabs['operation']['text'] = __('Operations');
439 $tabs['operation']['icon'] = 'b_tblops';
440 $tabs['operation']['active'] = $route === '/database/operations';
442 if ($is_superuser || $isCreateOrGrantUser) {
443 $tabs['privileges']['route'] = '/server/privileges';
444 $tabs['privileges']['args']['checkprivsdb'] = $this->db;
445 // stay on database view
446 $tabs['privileges']['args']['viewing_mode'] = 'db';
447 $tabs['privileges']['text'] = __('Privileges');
448 $tabs['privileges']['icon'] = 's_rights';
449 $tabs['privileges']['active'] = $route === '/server/privileges';
452 $tabs['routines']['route'] = '/database/routines';
453 $tabs['routines']['text'] = __('Routines');
454 $tabs['routines']['icon'] = 'b_routines';
455 $tabs['routines']['active'] = $route === '/database/routines';
457 if (Util::currentUserHasPrivilege('EVENT', $this->db)) {
458 $tabs['events']['route'] = '/database/events';
459 $tabs['events']['text'] = __('Events');
460 $tabs['events']['icon'] = 'b_events';
461 $tabs['events']['active'] = $route === '/database/events';
464 if (Util::currentUserHasPrivilege('TRIGGER', $this->db)) {
465 $tabs['triggers']['route'] = '/database/triggers';
466 $tabs['triggers']['text'] = __('Triggers');
467 $tabs['triggers']['icon'] = 'b_triggers';
468 $tabs['triggers']['active'] = $route === '/database/triggers';
472 if (Tracker::isActive() && ! $isSystemSchema) {
473 $tabs['tracking']['text'] = __('Tracking');
474 $tabs['tracking']['icon'] = 'eye';
475 $tabs['tracking']['route'] = '/database/tracking';
476 $tabs['tracking']['active'] = $route === '/database/tracking';
479 if (! $isSystemSchema) {
480 $tabs['designer']['text'] = __('Designer');
481 $tabs['designer']['icon'] = 'b_relations';
482 $tabs['designer']['route'] = '/database/designer';
483 $tabs['designer']['active'] = $route === '/database/designer';
486 if (! $isSystemSchema
487 && $cfgRelation['centralcolumnswork']
489 $tabs['central_columns']['text'] = __('Central columns');
490 $tabs['central_columns']['icon'] = 'centralColumns';
491 $tabs['central_columns']['route'] = '/database/central-columns';
492 $tabs['central_columns']['active'] = $route === '/database/central-columns';
495 return $tabs;
499 * Returns the server tabs as an array
501 * @return array Data for generating server tabs
503 private function getServerTabs()
505 /** @var DatabaseInterface $dbi */
506 global $route, $dbi;
508 $is_superuser = $dbi->isSuperUser();
509 $isCreateOrGrantUser = $dbi->isGrantUser() || $dbi->isCreateUser();
510 if (SessionCache::has('binary_logs')) {
511 $binary_logs = SessionCache::get('binary_logs');
512 } else {
513 $binary_logs = $dbi->fetchResult(
514 'SHOW MASTER LOGS',
515 'Log_name',
516 null,
517 DatabaseInterface::CONNECT_USER,
518 DatabaseInterface::QUERY_STORE
520 SessionCache::set('binary_logs', $binary_logs);
523 $tabs = [];
525 $tabs['databases']['icon'] = 's_db';
526 $tabs['databases']['route'] = '/server/databases';
527 $tabs['databases']['text'] = __('Databases');
528 $tabs['databases']['active'] = $route === '/server/databases';
530 $tabs['sql']['icon'] = 'b_sql';
531 $tabs['sql']['route'] = '/server/sql';
532 $tabs['sql']['text'] = __('SQL');
533 $tabs['sql']['active'] = $route === '/server/sql';
535 $tabs['status']['icon'] = 's_status';
536 $tabs['status']['route'] = '/server/status';
537 $tabs['status']['text'] = __('Status');
538 $tabs['status']['active'] = in_array($route, [
539 '/server/status',
540 '/server/status/advisor',
541 '/server/status/monitor',
542 '/server/status/processes',
543 '/server/status/queries',
544 '/server/status/variables',
547 if ($is_superuser || $isCreateOrGrantUser) {
548 $tabs['rights']['icon'] = 's_rights';
549 $tabs['rights']['route'] = '/server/privileges';
550 $tabs['rights']['text'] = __('User accounts');
551 $tabs['rights']['active'] = in_array($route, [
552 '/server/privileges',
553 '/server/user-groups',
555 $tabs['rights']['args']['viewing_mode'] = 'server';
558 $tabs['export']['icon'] = 'b_export';
559 $tabs['export']['route'] = '/server/export';
560 $tabs['export']['text'] = __('Export');
561 $tabs['export']['active'] = $route === '/server/export';
563 $tabs['import']['icon'] = 'b_import';
564 $tabs['import']['route'] = '/server/import';
565 $tabs['import']['text'] = __('Import');
566 $tabs['import']['active'] = $route === '/server/import';
568 $tabs['settings']['icon'] = 'b_tblops';
569 $tabs['settings']['route'] = '/preferences/manage';
570 $tabs['settings']['text'] = __('Settings');
571 $tabs['settings']['active'] = in_array($route, [
572 '/preferences/export',
573 '/preferences/features',
574 '/preferences/import',
575 '/preferences/main-panel',
576 '/preferences/manage',
577 '/preferences/navigation',
578 '/preferences/sql',
579 '/preferences/two-factor',
582 if (! empty($binary_logs)) {
583 $tabs['binlog']['icon'] = 's_tbl';
584 $tabs['binlog']['route'] = '/server/binlog';
585 $tabs['binlog']['text'] = __('Binary log');
586 $tabs['binlog']['active'] = $route === '/server/binlog';
589 if ($is_superuser) {
590 $tabs['replication']['icon'] = 's_replication';
591 $tabs['replication']['route'] = '/server/replication';
592 $tabs['replication']['text'] = __('Replication');
593 $tabs['replication']['active'] = $route === '/server/replication';
596 $tabs['vars']['icon'] = 's_vars';
597 $tabs['vars']['route'] = '/server/variables';
598 $tabs['vars']['text'] = __('Variables');
599 $tabs['vars']['active'] = $route === '/server/variables';
601 $tabs['charset']['icon'] = 's_asci';
602 $tabs['charset']['route'] = '/server/collations';
603 $tabs['charset']['text'] = __('Charsets');
604 $tabs['charset']['active'] = $route === '/server/collations';
606 $tabs['engine']['icon'] = 'b_engine';
607 $tabs['engine']['route'] = '/server/engines';
608 $tabs['engine']['text'] = __('Engines');
609 $tabs['engine']['active'] = $route === '/server/engines';
611 $tabs['plugins']['icon'] = 'b_plugin';
612 $tabs['plugins']['route'] = '/server/plugins';
613 $tabs['plugins']['text'] = __('Plugins');
614 $tabs['plugins']['active'] = $route === '/server/plugins';
616 return $tabs;
620 * Set current table
622 * @param string $table Current table
624 * @return Menu
626 public function setTable($table)
628 $this->table = $table;
630 return $this;