/
var
/
www
/
html
/
restaurants
/
var
/
phpmyadmin
/
tests
/
unit
/
Controllers
/
Upload File
HOME
<?php declare(strict_types=1); namespace PhpMyAdmin\Tests\Controllers; use PhpMyAdmin\Config; use PhpMyAdmin\Config\PageSettings; use PhpMyAdmin\ConfigStorage\Relation; use PhpMyAdmin\Controllers\NavigationController; use PhpMyAdmin\Current; use PhpMyAdmin\DatabaseInterface; use PhpMyAdmin\Http\ServerRequest; use PhpMyAdmin\Navigation\Navigation; use PhpMyAdmin\Template; use PhpMyAdmin\Tests\AbstractTestCase; use PhpMyAdmin\Tests\Stubs\DbiDummy; use PhpMyAdmin\Tests\Stubs\ResponseRenderer; use PhpMyAdmin\UserPreferences; use PHPUnit\Framework\Attributes\CoversClass; use function sprintf; #[CoversClass(NavigationController::class)] class NavigationControllerTest extends AbstractTestCase { protected DatabaseInterface $dbi; protected DbiDummy $dummyDbi; protected function setUp(): void { parent::setUp(); $this->dummyDbi = $this->createDbiDummy(); $this->dbi = $this->createDatabaseInterface($this->dummyDbi); DatabaseInterface::$instance = $this->dbi; } public function testIndex(): void { $this->setLanguage(); Current::$database = 'air-balloon_burner_dev2'; $config = Config::getInstance(); $config->selectedServer['DisableIS'] = false; $config->selectedServer['auth_type'] = 'cookie'; // This example path data has nothing to do with the actual test // root.air-balloon_burner_dev2 $_POST['n0_aPath'] = 'cm9vdA==.YWlyLWJhbGxvb25fYnVybmVyX2RldjI='; // root.air-balloon.burner_dev2 $_POST['n0_vPath'] = 'cm9vdA==.YWlyLWJhbGxvb24=.YnVybmVyX2RldjI='; $this->dummyDbi->removeDefaultResults(); $this->dummyDbi->addResult( 'SELECT CURRENT_USER();', [['pma_test@localhost']], ); $this->dummyDbi->addResult( 'SHOW GRANTS', [], ); $this->dummyDbi->addResult( 'SELECT (COUNT(DB_first_level) DIV 100) * 100 from (' . ' SELECT distinct SUBSTRING_INDEX(SCHEMA_NAME, \'_\', 1) DB_first_level ' . 'FROM INFORMATION_SCHEMA.SCHEMATA WHERE `SCHEMA_NAME` < \'air-balloon_burner_dev2\' ) t', [], ); $this->dummyDbi->addResult( 'SELECT `SCHEMA_NAME` FROM `INFORMATION_SCHEMA`.`SCHEMATA`, ' . '(SELECT DB_first_level FROM ( SELECT DISTINCT ' . "SUBSTRING_INDEX(SCHEMA_NAME, '_', 1) DB_first_level " . 'FROM INFORMATION_SCHEMA.SCHEMATA WHERE TRUE ) t ORDER BY ' . 'DB_first_level ASC LIMIT 0, 100) t2 WHERE TRUE AND 1 = LOCATE(' . "CONCAT(DB_first_level, '_'), CONCAT(SCHEMA_NAME, '_')) " . 'ORDER BY SCHEMA_NAME ASC', [['air-balloon_burner_dev2']], ['SCHEMA_NAME'], ); $sqlCount = 'SELECT COUNT(*) FROM ( SELECT DISTINCT SUBSTRING_INDEX(SCHEMA_NAME, \'_\', 1) ' . 'DB_first_level FROM INFORMATION_SCHEMA.SCHEMATA WHERE TRUE ) t'; $this->dummyDbi->addResult( $sqlCount, [[179]], ); $this->dummyDbi->addResult( $sqlCount, [[179]], ); $this->dummyDbi->addResult( 'SELECT `TABLE_NAME` AS `name`, `TABLE_TYPE` AS `type` FROM `INFORMATION_SCHEMA`.`TABLES`' . ' WHERE `TABLE_SCHEMA`=\'air-balloon_burner_dev2\' ORDER BY `TABLE_NAME` ASC', [], ); $this->dummyDbi->addResult('SELECT @@lower_case_table_names', [['0']]); $this->dummyDbi->addResult( 'SELECT `ROUTINE_NAME` AS `name` FROM `INFORMATION_SCHEMA`.`ROUTINES` WHERE ' . '`ROUTINE_SCHEMA` COLLATE utf8_bin=\'air-balloon_burner_dev2\' AND `ROUTINE_TYPE`=\'FUNCTION\' ' . 'ORDER BY `ROUTINE_NAME` ASC', [], ); $this->dummyDbi->addResult( 'SELECT `ROUTINE_NAME` AS `name` FROM `INFORMATION_SCHEMA`.`ROUTINES` WHERE ' . '`ROUTINE_SCHEMA` COLLATE utf8_bin=\'air-balloon_burner_dev2\' AND `ROUTINE_TYPE`=\'PROCEDURE\' ' . 'ORDER BY `ROUTINE_NAME` ASC', [], ); $this->dummyDbi->addResult( 'SELECT `EVENT_NAME` AS `name` FROM `INFORMATION_SCHEMA`.`EVENTS`' . ' WHERE `EVENT_SCHEMA` COLLATE utf8_bin=\'air-balloon_burner_dev2\' ORDER BY `EVENT_NAME` ASC', [], ); $responseRenderer = new ResponseRenderer(); $template = new Template(); $relation = new Relation($this->dbi); $navigationController = new NavigationController( $responseRenderer, $template, new Navigation($template, $relation, $this->dbi, $config), $relation, new PageSettings(new UserPreferences($this->dbi, $relation, $template)), ); $_POST['full'] = '1'; $request = self::createStub(ServerRequest::class); $request->method('isAjax')->willReturn(true); $navigationController($request); self::assertTrue($responseRenderer->hasSuccessState(), 'expected the request not to fail'); $responseMessage = $responseRenderer->getJSONResult()['message']; self::assertStringContainsString('<div id=\'pma_navigation_tree_content\'>', $responseMessage); // root.air-balloon_burner_dev2 // cm9vdA==.YWlyLWJhbGxvb25fYnVybmVyX2RldjI= self::assertStringContainsString( '<div id=\'pma_navigation_tree_content\'>' . "\n" . ' <ul>' . "\n" . ' <li class="first database">' . "\n" . ' <div class="block">' . "\n" . ' <i class="first"></i>' . "\n" . ' <b></b>' . "\n" . ' <a class="expander" href="#">' . "\n" . ' <span class="hide paths_nav" data-apath="cm9vdA==.YWlyLWJhbGxvb25fYnVybmVyX2RldjI="' . ' data-vpath="cm9vdA==.YWlyLWJhbGxvb25fYnVybmVyX2RldjI="' . ' data-pos="0"></span>' . "\n" . ' <img src="themes/dot.gif" title="Expand/Collapse"' . ' alt="Expand/Collapse" class="icon ic_b_plus">' . "\n" . ' </a>' . "\n" . ' </div>' . "\n" . ' ' . "\n" . ' <div class="block second">' . "\n" . ' <a href="index.php?route=/database/operations' . '&db=air-balloon_burner_dev2&lang=en" class="disableAjax">' . '<img src="themes/dot.gif" title="Database operations"' . ' alt="Database operations" class="icon ic_s_db"></a>' . "\n" . ' </div>' . "\n" . "\n" . ' <a class="hover_show_full disableAjax"' . ' href="index.php?route=/database/structure&db=air-balloon_burner_dev2&lang=en"' . ' title="Structure">air-balloon_burner_dev2</a>' . "\n" . ' ' . "\n" . ' ' . "\n" . "\n" . ' ' . "\n" . ' <div class="clearfloat"></div>' . "\n" . "\n" . "\n" . "\n" . "\n" . ' </ul>' . "\n" . '</div>', $responseMessage, ); $this->dummyDbi->assertAllQueriesConsumed(); } public function testIndexWithPosAndValue(): void { $this->setLanguage(); Current::$database = 'air-balloon_burner_dev2'; $config = Config::getInstance(); $config->selectedServer['DisableIS'] = false; $config->selectedServer['auth_type'] = 'cookie'; // root.air-balloon_burner_dev2 $_POST['n0_aPath'] = 'cm9vdA==.YWlyLWJhbGxvb25fYnVybmVyX2RldjI='; // root.air-balloon.burner_dev2 $_POST['n0_vPath'] = 'cm9vdA==.YWlyLWJhbGxvb24=.YnVybmVyX2RldjI='; $_POST['n0_pos2_name'] = 'tables'; $_POST['n0_pos2_value'] = 0; $this->dummyDbi->removeDefaultResults(); $this->dummyDbi->addResult( 'SELECT CURRENT_USER();', [['pma_test@localhost']], ); $this->dummyDbi->addResult( 'SHOW GRANTS', [], ); $this->dummyDbi->addResult( 'SELECT (COUNT(DB_first_level) DIV 100) * 100 from (' . ' SELECT distinct SUBSTRING_INDEX(SCHEMA_NAME, \'_\', 1) DB_first_level ' . 'FROM INFORMATION_SCHEMA.SCHEMATA WHERE `SCHEMA_NAME` < \'air-balloon_burner_dev2\' ) t', [], ); $this->dummyDbi->addResult( 'SELECT `SCHEMA_NAME` FROM `INFORMATION_SCHEMA`.`SCHEMATA`, ' . '(SELECT DB_first_level FROM ( SELECT DISTINCT ' . "SUBSTRING_INDEX(SCHEMA_NAME, '_', 1) DB_first_level " . 'FROM INFORMATION_SCHEMA.SCHEMATA WHERE TRUE ) t ORDER BY ' . 'DB_first_level ASC LIMIT 0, 100) t2 WHERE TRUE AND 1 = LOCATE(' . "CONCAT(DB_first_level, '_'), CONCAT(SCHEMA_NAME, '_')) " . 'ORDER BY SCHEMA_NAME ASC', [['air-balloon_burner_dev'], ['air-balloon_burner_dev2'], ['air-balloon_dev']], ['SCHEMA_NAME'], ); $sqlCount = 'SELECT COUNT(*) FROM ( SELECT DISTINCT SUBSTRING_INDEX(SCHEMA_NAME, \'_\', 1) ' . 'DB_first_level FROM INFORMATION_SCHEMA.SCHEMATA WHERE TRUE ) t'; $this->dummyDbi->addResult( $sqlCount, [[179]], ); $this->dummyDbi->addResult( $sqlCount, [[179]], ); $this->dummyDbi->addResult( 'SELECT `TABLE_NAME` AS `name`, `TABLE_TYPE` AS `type` FROM `INFORMATION_SCHEMA`.`TABLES`' . ' WHERE `TABLE_SCHEMA`=\'air-balloon_burner_dev2\' ORDER BY `TABLE_NAME` ASC', [], ); $this->dummyDbi->addResult('SELECT @@lower_case_table_names', [['0']]); $this->dummyDbi->addResult( 'SELECT `ROUTINE_NAME` AS `name` FROM `INFORMATION_SCHEMA`.`ROUTINES` WHERE ' . '`ROUTINE_SCHEMA` COLLATE utf8_bin=\'air-balloon_burner_dev2\' AND `ROUTINE_TYPE`=\'FUNCTION\' ' . 'ORDER BY `ROUTINE_NAME` ASC', [], ); $this->dummyDbi->addResult( 'SELECT `EVENT_NAME` AS `name` FROM `INFORMATION_SCHEMA`.`EVENTS` WHERE' . ' `EVENT_SCHEMA` COLLATE utf8_bin=\'air-balloon_burner_dev2\' ORDER BY `EVENT_NAME` ASC', [], ); $this->dummyDbi->addResult( 'SELECT `ROUTINE_NAME` AS `name` FROM `INFORMATION_SCHEMA`.`ROUTINES` WHERE ' . '`ROUTINE_SCHEMA` COLLATE utf8_bin=\'air-balloon_burner_dev2\' AND `ROUTINE_TYPE`=\'PROCEDURE\' ' . 'ORDER BY `ROUTINE_NAME` ASC', [], ); $responseRenderer = new ResponseRenderer(); $template = new Template(); $relation = new Relation($this->dbi); $navigationController = new NavigationController( $responseRenderer, $template, new Navigation($template, $relation, $this->dbi, $config), $relation, new PageSettings(new UserPreferences($this->dbi, $relation, $template)), ); $_POST['full'] = '1'; $request = self::createStub(ServerRequest::class); $request->method('isAjax')->willReturn(true); $navigationController($request); self::assertTrue($responseRenderer->hasSuccessState(), 'expected the request not to fail'); $responseMessage = $responseRenderer->getJSONResult()['message']; self::assertStringContainsString('<div id=\'pma_navigation_tree_content\'>', $responseMessage); $dbTemplate = ' <li class="database database">' . "\n" . ' <div class="block">' . "\n" . ' <i></i>' . "\n" . ' <b></b>' . "\n" . ' <a class="expander" href="#">' . "\n" . ' <span class="hide paths_nav" data-apath="%s" data-vpath="%s" data-pos="0"></span>' . "\n" . ' <img src="themes/dot.gif" title="Expand/Collapse" alt="Expand/Collapse"' . ' class="icon ic_b_plus">' . "\n" . ' </a>' . "\n" . ' </div>' . "\n" . ' ' . "\n" . ' <div class="block second">' . "\n" . ' <a href="index.php?route=/database/operations&db=%s&lang=en" class="disableAjax">' . '<img src="themes/dot.gif" title="Database operations" alt="Database operations"' . ' class="icon ic_s_db"></a>' . "\n" . ' </div>' . "\n" . "\n" . ' <a class="hover_show_full disableAjax"' . ' href="index.php?route=/database/structure&db=%s&lang=en" title="Structure">%s</a>' . "\n" . ' ' . "\n" . ' ' . "\n" . "\n" . ' ' . "\n" . ' <div class="clearfloat"></div>' . "\n" . "\n" . "\n" . "\n" . ' </li>'; $dbTemplateLast = ' <li class="database last database">' . "\n"// "last" class added . ' <div class="block">' . "\n" . ' <i></i>' . "\n" . ' ' . "\n"// <b> node is removed . ' <a class="expander" href="#">' . "\n" . ' <span class="hide paths_nav" data-apath="%s" data-vpath="%s" data-pos="0"></span>' . "\n" . ' <img src="themes/dot.gif" title="Expand/Collapse" alt="Expand/Collapse"' . ' class="icon ic_b_plus">' . "\n" . ' </a>' . "\n" . ' </div>' . "\n" . ' ' . "\n" . ' <div class="block second">' . "\n" . ' <a href="index.php?route=/database/operations&db=%s&lang=en" class="disableAjax">' . '<img src="themes/dot.gif" title="Database operations" alt="Database operations"' . ' class="icon ic_s_db"></a>' . "\n" . ' </div>' . "\n" . "\n" . ' <a class="hover_show_full disableAjax"' . ' href="index.php?route=/database/structure&db=%s&lang=en" title="Structure">%s</a>' . "\n" . ' ' . "\n" . ' ' . "\n" . "\n" . ' ' . "\n" . ' <div class="clearfloat"></div>' . "\n" . "\n" . "\n" . "\n" . ' </li>'; $dbTemplateExpanded = ' <li class="database database">' . "\n" . ' <div class="block">' . "\n" . ' <i></i>' . "\n" . ' <b></b>' . "\n" . ' <a class="expander loaded" href="#">' . "\n" . ' <span class="hide paths_nav" data-apath="%s" data-vpath="%s" data-pos="0"></span>' . "\n" . ' <img src="themes/dot.gif" title="" alt=""'// title and alt changes . ' class="icon ic_b_minus">' . "\n"// Icon changes . ' </a>' . "\n" . ' </div>' . "\n" . ' ' . "\n" . ' <div class="block second">' . "\n" . ' <a href="index.php?route=/database/operations&db=%s&lang=en" class="disableAjax">' . '<img src="themes/dot.gif" title="Database operations" alt="Database operations"' . ' class="icon ic_s_db"></a>' . "\n" . ' </div>' . "\n" . "\n" . ' <a class="hover_show_full disableAjax"' . ' href="index.php?route=/database/structure&db=%s&lang=en" title="Structure">%s</a>' . "\n" . ' ' . "\n" . ' ' . "\n" . "\n" . ' ' . "\n" . ' <div class="clearfloat"></div>' . "\n" . "\n" . "\n" . "\n" . ' </li>'; // root.air-balloon_burner_dev2 // cm9vdA==.YWlyLWJhbGxvb25fYnVybmVyX2RldjI= self::assertStringContainsString( '<div id=\'pma_navigation_tree_content\'>' . "\n" . ' <ul>' . "\n" . ' <li class="first navGroup">' . "\n" . ' <div class="block">' . "\n" . ' <i class="first"></i>' . "\n" . ' <b></b>' . "\n" . ' <a class="expander loaded container" href="#">' . "\n" . ' <span class="hide paths_nav" data-apath="cm9vdA=="' . ' data-vpath="cm9vdA==.YWlyLWJhbGxvb24="' . ' data-pos="0"></span>' . "\n" . ' <img src="themes/dot.gif" title="" alt="" class="icon ic_b_minus">' . "\n" . ' </a>' . "\n" . ' </div>' . "\n" . ' <div class="fst-italic">' . "\n" . ' ' . "\n" . ' <div class="block second">' . "\n" . ' <u><img src="themes/dot.gif" title="Groups" alt="Groups" class="icon ic_b_group"></u>' . "\n" . ' </div>' . "\n" . ' air-balloon' . "\n" . ' ' . "\n" . ' ' . "\n" . "\n" . ' </div>' . "\n" . ' ' . "\n" . ' <div class="clearfloat"></div>' . "\n" . "\n" . ' <div class="list_container">' . "\n" . ' <ul>' . "\n" . sprintf( $dbTemplate, 'cm9vdA==.YWlyLWJhbGxvb25fYnVybmVyX2Rldg==', 'cm9vdA==.YWlyLWJhbGxvb24=.YnVybmVyX2Rldg==', 'air-balloon_burner_dev', 'air-balloon_burner_dev', 'air-balloon_burner_dev', ) . "\n" . sprintf( $dbTemplateExpanded, 'cm9vdA==.YWlyLWJhbGxvb25fYnVybmVyX2RldjI=', 'cm9vdA==.YWlyLWJhbGxvb24=.YnVybmVyX2RldjI=', 'air-balloon_burner_dev2', 'air-balloon_burner_dev2', 'air-balloon_burner_dev2', ) . "\n" . sprintf( $dbTemplateLast, 'cm9vdA==.YWlyLWJhbGxvb25fZGV2', 'cm9vdA==.YWlyLWJhbGxvb24=.ZGV2', 'air-balloon_dev', 'air-balloon_dev', 'air-balloon_dev', ) . "\n" . "\n" . ' </ul>' . "\n" . ' </div>' . "\n" . "\n" . "\n" . ' </ul>' . "\n" . '</div>' . "\n", $responseMessage, ); $this->dummyDbi->assertAllQueriesConsumed(); } }