Skip to content

Commit

Permalink
Refactor Routing::callSetupController() to use ContainerBuilder
Browse files Browse the repository at this point in the history
Uses the ContainerBuilder to factory the setup controllers.

Signed-off-by: Maurício Meneghini Fauth <mauricio@fauth.dev>
  • Loading branch information
MauricioFauth committed May 10, 2024
1 parent c6c9aeb commit ae62570
Show file tree
Hide file tree
Showing 5 changed files with 96 additions and 39 deletions.
13 changes: 13 additions & 0 deletions app/services_controllers.php
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
use PhpMyAdmin\Controllers\Preferences;
use PhpMyAdmin\Controllers\SchemaExportController;
use PhpMyAdmin\Controllers\Server;
use PhpMyAdmin\Controllers\Setup;
use PhpMyAdmin\Controllers\Sql;
use PhpMyAdmin\Controllers\Table;
use PhpMyAdmin\Controllers\TableController;
Expand Down Expand Up @@ -866,6 +867,18 @@
'class' => Server\VariablesController::class,
'arguments' => ['$response' => '@response', '$template' => '@template', '$dbi' => '@dbi'],
],
Setup\MainController::class => [
'class' => Setup\MainController::class,
'arguments' => ['@' . ResponseFactory::class, '@template', '@console'],
],
Setup\ShowConfigController::class => [
'class' => Setup\ShowConfigController::class,
'arguments' => ['@response'],
],
Setup\ValidateController::class => [
'class' => Setup\ValidateController::class,
'arguments' => ['@' . ResponseFactory::class],
],
Sql\ColumnPreferencesController::class => [
'class' => Sql\ColumnPreferencesController::class,
'arguments' => ['$response' => '@response', '$dbi' => '@dbi'],
Expand Down
14 changes: 13 additions & 1 deletion psalm-baseline.xml
Original file line number Diff line number Diff line change
Expand Up @@ -3029,6 +3029,19 @@
<DeprecatedMethod>
<code><![CDATA[Config::getInstance()]]></code>
</DeprecatedMethod>
<PossiblyUnusedMethod>
<code><![CDATA[__construct]]></code>
</PossiblyUnusedMethod>
</file>
<file src="src/Controllers/Setup/ShowConfigController.php">
<PossiblyUnusedMethod>
<code><![CDATA[__construct]]></code>
</PossiblyUnusedMethod>
</file>
<file src="src/Controllers/Setup/ValidateController.php">
<PossiblyUnusedMethod>
<code><![CDATA[__construct]]></code>
</PossiblyUnusedMethod>
</file>
<file src="src/Controllers/Sql/ColumnPreferencesController.php">
<MixedAssignment>
Expand Down Expand Up @@ -10221,7 +10234,6 @@
<file src="src/Routing/Routing.php">
<DeprecatedMethod>
<code><![CDATA[Config::getInstance()]]></code>
<code><![CDATA[DatabaseInterface::getInstance()]]></code>
</DeprecatedMethod>
<MixedArrayAccess>
<code><![CDATA[$dispatchData[0]['GET']['/']]]></code>
Expand Down
26 changes: 16 additions & 10 deletions src/Controllers/Setup/ShowConfigController.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,13 +18,16 @@

final class ShowConfigController implements InvocableController
{
public function __construct(private readonly ResponseRenderer $responseRenderer)
{
}

public function __invoke(ServerRequest $request): Response
{
$formDisplay = new ConfigForm($GLOBALS['ConfigFile']);
$formDisplay->save(['Config']);

$response = ResponseRenderer::getInstance();
$response->disable();
$this->responseRenderer->disable();

/** @var mixed $eol */
$eol = $request->getParsedBodyParam('eol');
Expand All @@ -38,30 +41,33 @@ public function __invoke(ServerRequest $request): Response
// Clear current config and return to main page
$GLOBALS['ConfigFile']->resetConfigData();
// drop post data
$response->addHeader('Location', '../setup/index.php' . Url::getCommonRaw(['route' => '/setup']));
$response->setStatusCode(StatusCodeInterface::STATUS_SEE_OTHER);
$this->responseRenderer->addHeader(
'Location',
'../setup/index.php' . Url::getCommonRaw(['route' => '/setup']),
);
$this->responseRenderer->setStatusCode(StatusCodeInterface::STATUS_SEE_OTHER);

return $response->response();
return $this->responseRenderer->response();
}

/** @var mixed $submitDownload */
$submitDownload = $request->getParsedBodyParam('submit_download');
if (is_string($submitDownload) && $submitDownload !== '') {
// Output generated config file
Core::downloadHeader('config.inc.php', 'text/plain');
$response->disable();
$this->responseRenderer->disable();
echo ConfigGenerator::getConfigFile($GLOBALS['ConfigFile']);

return $response->response();
return $this->responseRenderer->response();
}

// Show generated config file in a <textarea>
$response->addHeader(
$this->responseRenderer->addHeader(
'Location',
'../setup/index.php' . Url::getCommonRaw(['route' => '/setup', 'page' => 'config']),
);
$response->setStatusCode(StatusCodeInterface::STATUS_SEE_OTHER);
$this->responseRenderer->setStatusCode(StatusCodeInterface::STATUS_SEE_OTHER);

return $response->response();
return $this->responseRenderer->response();
}
}
51 changes: 24 additions & 27 deletions src/Routing/Routing.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,14 @@
use FastRoute\RouteCollector;
use FastRoute\RouteParser\Std as RouteParserStd;
use Fig\Http\Message\StatusCodeInterface;
use PhpMyAdmin\Bookmarks\BookmarkRepository;
use PhpMyAdmin\Config;
use PhpMyAdmin\ConfigStorage\Relation;
use PhpMyAdmin\Console;
use PhpMyAdmin\Container\ContainerBuilder;
use PhpMyAdmin\Controllers\HomeController;
use PhpMyAdmin\Controllers\InvocableController;
use PhpMyAdmin\Controllers\Setup\MainController;
use PhpMyAdmin\Controllers\Setup\ShowConfigController;
use PhpMyAdmin\Controllers\Setup\ValidateController;
use PhpMyAdmin\Core;
use PhpMyAdmin\DatabaseInterface;
use PhpMyAdmin\Http\Factory\ResponseFactory;
use PhpMyAdmin\Http\Response;
use PhpMyAdmin\Http\ServerRequest;
Expand Down Expand Up @@ -190,33 +187,33 @@ private static function isRoutesCacheFileValid(mixed $dispatchData): bool
public static function callSetupController(ServerRequest $request, ResponseFactory $responseFactory): Response
{
$route = $request->getRoute();
$template = new Template();
if ($route === '/setup' || $route === '/') {
$dbi = DatabaseInterface::getInstance();
$relation = new Relation($dbi);
$console = new Console($relation, $template, new BookmarkRepository($dbi, $relation));

return (new MainController($responseFactory, $template, $console))($request);
}

if ($route === '/setup/show-config') {
return (new ShowConfigController())($request);
}
$controllerName = match ($route) {
'/', '/setup' => MainController::class,
'/setup/show-config' => ShowConfigController::class,
'/setup/validate' => ValidateController::class,
default => null,
};

$container = ContainerBuilder::getContainer();
if ($controllerName === null) {
$template = $container->get('template');
assert($template instanceof Template);
$response = $responseFactory->createResponse(StatusCodeInterface::STATUS_NOT_FOUND);

if ($route === '/setup/validate') {
return (new ValidateController($responseFactory))($request);
return $response->write($template->render('error/generic', [
'lang' => $GLOBALS['lang'] ?? 'en',
'dir' => LanguageManager::$textDir,
'error_message' => Sanitize::convertBBCode(sprintf(
__('Error 404! The page %s was not found.'),
'[code]' . htmlspecialchars($route) . '[/code]',
)),
]));
}

$response = $responseFactory->createResponse(StatusCodeInterface::STATUS_NOT_FOUND);
$controller = $container->get($controllerName);
assert($controller instanceof $controllerName);

return $response->write($template->render('error/generic', [
'lang' => $GLOBALS['lang'] ?? 'en',
'dir' => LanguageManager::$textDir,
'error_message' => Sanitize::convertBBCode(sprintf(
__('Error 404! The page %s was not found.'),
'[code]' . htmlspecialchars($route) . '[/code]',
)),
]));
return $controller($request);
}

/**
Expand Down
31 changes: 30 additions & 1 deletion tests/unit/Routing/RoutingTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,18 @@
namespace PhpMyAdmin\Tests\Routing;

use FastRoute\Dispatcher;
use Fig\Http\Message\StatusCodeInterface;
use PhpMyAdmin\Config;
use PhpMyAdmin\Container\ContainerBuilder;
use PhpMyAdmin\Controllers\HomeController;
use PhpMyAdmin\Http\Factory\ResponseFactory;
use PhpMyAdmin\Http\Factory\ServerRequestFactory;
use PhpMyAdmin\Routing\Routing;
use PhpMyAdmin\Template;
use PhpMyAdmin\Tests\AbstractTestCase;
use PHPUnit\Framework\Attributes\CoversClass;
use PHPUnit\Framework\Attributes\DataProvider;
use Psr\Container\ContainerInterface;

use function copy;
use function unlink;
Expand All @@ -19,7 +25,7 @@
use const TEST_PATH;

#[CoversClass(Routing::class)]
class RoutingTest extends AbstractTestCase
final class RoutingTest extends AbstractTestCase
{
/**
* Test for Routing::getDispatcher
Expand Down Expand Up @@ -97,4 +103,27 @@ public static function providerForTestCleanupPathInfo(): array
['', '/phpmyadmin/index.php', '', '/phpmyadmin/index.php'],
];
}

public function testCallSetupControllerWithInvalidRoute(): void
{
$template = new Template();
$container = self::createStub(ContainerInterface::class);
$container->method('get')->willReturn($template);
ContainerBuilder::$container = $container;

$request = ServerRequestFactory::create()->createServerRequest('GET', 'https://example.com/')
->withAttribute('route', '/setup/invalid-route');
$response = Routing::callSetupController($request, ResponseFactory::create());

$expected = $template->render('error/generic', [
'lang' => 'en',
'dir' => 'ltr',
'error_message' => 'Error 404! The page <code>/setup/invalid-route</code> was not found.',
]);

self::assertSame(StatusCodeInterface::STATUS_NOT_FOUND, $response->getStatusCode());
self::assertSame($expected, (string) $response->getBody());

ContainerBuilder::$container = null;
}
}

0 comments on commit ae62570

Please sign in to comment.