Merge pull request #19180 from MauricioFauth/responserenderer

Refactor ResponseRenderer contructor and response method
This commit is contained in:
Maurício Meneghini Fauth 2024-05-26 13:21:30 -03:00 committed by GitHub
commit 560cafbbc7
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 180 additions and 79 deletions

View File

@ -12282,7 +12282,7 @@ parameters:
-
message: "#^Construct empty\\(\\) is not allowed\\. Use more strict comparison\\.$#"
count: 5
count: 4
path: src/ResponseRenderer.php
-

View File

@ -10159,7 +10159,6 @@
<DeprecatedMethod>
<code><![CDATA[Config::getInstance()]]></code>
<code><![CDATA[DatabaseInterface::getInstance()]]></code>
<code><![CDATA[DatabaseInterface::getInstance()]]></code>
</DeprecatedMethod>
<InvalidArrayOffset>
<code><![CDATA[$GLOBALS['focus_querywindow']]]></code>
@ -10173,7 +10172,6 @@
</MixedAssignment>
<RiskyTruthyFalsyComparison>
<code><![CDATA[empty($GLOBALS['error_message'])]]></code>
<code><![CDATA[empty($_REQUEST['ajax_request'])]]></code>
<code><![CDATA[empty($_REQUEST['no_debug'])]]></code>
</RiskyTruthyFalsyComparison>
</file>

View File

@ -15,8 +15,6 @@ use PhpMyAdmin\Theme\ThemeManager;
use function array_merge;
use function defined;
use function gmdate;
use function header;
use function htmlspecialchars;
use function ini_get;
use function json_encode;
@ -210,8 +208,6 @@ class Header
/** @return mixed[] */
public function getDisplay(): array
{
$this->sendHttpHeaders();
$baseDir = defined('PMA_PATH_TO_BASEDIR') ? PMA_PATH_TO_BASEDIR : '';
/** @var ThemeManager $themeManager */
@ -338,27 +334,6 @@ class Header
return $retval;
}
/**
* Sends out the HTTP headers
*/
public function sendHttpHeaders(): void
{
if (defined('TESTSUITE')) {
return;
}
/**
* Sends http headers
*/
$GLOBALS['now'] = gmdate('D, d M Y H:i:s') . ' GMT';
$headers = $this->getHttpHeaders();
foreach ($headers as $name => $value) {
header(sprintf('%s: %s', $name, $value));
}
}
/** @return array<string, string> */
public function getHttpHeaders(): array
{
@ -545,4 +520,9 @@ class Header
{
$this->isTransformationWrapper = $isTransformationWrapper;
}
public function getConsole(): Console
{
return $this->console;
}
}

View File

@ -28,10 +28,6 @@ class ResponseRenderer
{
private static ResponseRenderer|null $instance = null;
/**
* Header instance
*/
protected Header $header;
/**
* HTML data to be used in the response
*/
@ -43,10 +39,7 @@ class ResponseRenderer
* @var mixed[]
*/
private array $JSON = [];
/**
* PhpMyAdmin\Footer instance
*/
protected Footer $footer;
/**
* Whether we are servicing an ajax request.
*/
@ -136,24 +129,16 @@ class ResponseRenderer
protected Response $response;
protected Template $template;
protected Config $config;
private function __construct()
{
$this->config = Config::getInstance();
$this->template = new Template();
$dbi = DatabaseInterface::getInstance();
$relation = new Relation($dbi);
$this->header = new Header(
$this->template,
new Console($relation, $this->template, new BookmarkRepository($dbi, $relation)),
$this->config,
);
$this->footer = new Footer($this->template, $this->config);
$this->response = ResponseFactory::create()->createResponse();
$this->setAjax(! empty($_REQUEST['ajax_request']));
protected function __construct(
protected Config $config,
protected Template $template,
protected Header $header,
protected Footer $footer,
protected ErrorHandler $errorHandler,
protected DatabaseInterface $dbi,
ResponseFactory $responseFactory,
) {
$this->response = $responseFactory->createResponse(StatusCodeInterface::STATUS_OK, 'OK');
}
/**
@ -172,10 +157,26 @@ class ResponseRenderer
*/
public static function getInstance(): ResponseRenderer
{
if (self::$instance === null) {
self::$instance = new ResponseRenderer();
if (self::$instance !== null) {
return self::$instance;
}
$config = Config::getInstance();
$template = new Template($config);
$dbi = DatabaseInterface::getInstance();
$relation = new Relation($dbi);
$console = new Console($relation, $template, new BookmarkRepository($dbi, $relation));
self::$instance = new ResponseRenderer(
$config,
$template,
new Header($template, $console, $config),
new Footer($template, $config),
ErrorHandler::getInstance(),
$dbi,
ResponseFactory::create(),
);
return self::$instance;
}
@ -271,7 +272,7 @@ class ResponseRenderer
$this->addJSON('title', '<title>' . $this->getHeader()->getPageTitle() . '</title>');
}
if (DatabaseInterface::getInstance()->isConnected()) {
if ($this->dbi->isConnected()) {
$this->addJSON('menu', $this->getHeader()->getMenu()->getDisplay());
}
@ -289,7 +290,7 @@ class ResponseRenderer
$this->addJSON('errors', $errors);
}
$promptPhpErrors = ErrorHandler::getInstance()->hasErrorsForPrompt();
$promptPhpErrors = $this->errorHandler->hasErrorsForPrompt();
$this->addJSON('promptPhpErrors', $promptPhpErrors);
if (empty($GLOBALS['error_message'])) {
@ -317,12 +318,6 @@ class ResponseRenderer
}
}
// Set the Content-Type header to JSON so that jQuery parses the
// response correctly.
foreach (Core::headerJSON() as $name => $value) {
$this->addHeader($name, $value);
}
$result = json_encode($this->JSON);
if ($result === false) {
return (string) json_encode([
@ -336,9 +331,19 @@ class ResponseRenderer
public function response(): Response
{
$this->response->getBody()->write($this->isAjax() ? $this->ajaxResponse() : $this->getDisplay());
if ($this->isAjax()) {
$headers = Core::headerJSON();
$body = $this->ajaxResponse();
} else {
$headers = $this->header->getHttpHeaders();
$body = $this->getDisplay();
}
return $this->response;
foreach ($headers as $name => $value) {
$this->response = $this->response->withHeader($name, $value);
}
return $this->response->write($body);
}
public function addHeader(string $name, string $value): void

View File

@ -5,19 +5,24 @@ declare(strict_types=1);
namespace PhpMyAdmin\Tests;
use Fig\Http\Message\StatusCodeInterface;
use PhpMyAdmin\Config;
use PhpMyAdmin\Current;
use PhpMyAdmin\DatabaseInterface;
use PhpMyAdmin\Header;
use PhpMyAdmin\Html\MySQLDocumentation;
use PhpMyAdmin\Message;
use PhpMyAdmin\ResponseRenderer;
use PhpMyAdmin\Scripts;
use PhpMyAdmin\Template;
use PhpMyAdmin\Version;
use PHPUnit\Framework\Attributes\CoversClass;
use ReflectionProperty;
use function array_column;
use function json_decode;
#[CoversClass(ResponseRenderer::class)]
class ResponseRendererTest extends AbstractTestCase
final class ResponseRendererTest extends AbstractTestCase
{
protected function setUp(): void
{
@ -107,4 +112,115 @@ class ResponseRendererTest extends AbstractTestCase
(new ReflectionProperty(ResponseRenderer::class, 'instance'))->setValue(null, null);
}
public function testHtmlResponse(): void
{
(new ReflectionProperty(ResponseRenderer::class, 'instance'))->setValue(null, null);
$_SERVER['SCRIPT_NAME'] = 'index.php';
Current::$server = 0;
$responseRenderer = ResponseRenderer::getInstance();
$responseRenderer->setAjax(false);
$responseRenderer->addHTML('<div>TEST</div>');
$response = $responseRenderer->response();
self::assertSame(StatusCodeInterface::STATUS_OK, $response->getStatusCode());
self::assertSame('text/html; charset=utf-8', $response->getHeaderLine('Content-Type'));
$header = $responseRenderer->getHeader();
self::assertSame(
(new Template(new Config()))->render('base', [
'header' => [
'lang' => 'en',
'allow_third_party_framing' => false,
'base_dir' => '',
'theme_path' => '',
'version' => 'v=' . Version::VERSION,
'text_dir' => 'ltr',
'server' => 0,
'title' => 'phpMyAdmin',
'scripts' => $header->getScripts()->getDisplay(),
'body_id' => '',
'navigation' => '',
'custom_header' => '',
'load_user_preferences' => '',
'show_hint' => true,
'is_warnings_enabled' => true,
'is_menu_enabled' => true,
'is_logged_in' => true,
'menu' => '',
'console' => $header->getConsole()->getDisplay(),
'messages' => '',
'theme_color_mode' => 'light',
'theme_color_modes' => ['light'],
'theme_id' => '',
'current_user' => ['pma_test', 'localhost'],
'is_mariadb' => false,
],
'content' => '<div>TEST</div>',
'footer' => [
'is_minimal' => false,
'self_url' => 'index.php?route=%2F&server=0&lang=en',
'error_messages' => '',
'scripts' => <<<'HTML'
<script data-cfasync="false">
// <![CDATA[
window.Console.debugSqlInfo = 'false';
// ]]>
</script>
HTML,
'is_demo' => false,
'git_revision_info' => [],
'footer' => '',
],
]),
(string) $response->getBody(),
);
(new ReflectionProperty(ResponseRenderer::class, 'instance'))->setValue(null, null);
}
public function testJsonResponse(): void
{
(new ReflectionProperty(ResponseRenderer::class, 'instance'))->setValue(null, null);
$_SERVER['SCRIPT_NAME'] = 'index.php';
Current::$server = 0;
$responseRenderer = ResponseRenderer::getInstance();
$responseRenderer->setAjax(true);
$responseRenderer->addJSON('message', 'test message');
$responseRenderer->addJSON('test', 'test');
$response = $responseRenderer->response();
self::assertSame(StatusCodeInterface::STATUS_OK, $response->getStatusCode());
self::assertSame('application/json; charset=UTF-8', $response->getHeaderLine('Content-Type'));
$body = (string) $response->getBody();
self::assertJson($body);
$header = $responseRenderer->getHeader();
self::assertEquals(
[
'message' => 'test message',
'test' => 'test',
'success' => true,
'title' => '<title>phpMyAdmin</title>',
'menu' => $header->getMenu()->getDisplay(),
'scripts' => $header->getScripts()->getFiles(),
'selflink' => 'index.php?route=%2F&server=0&lang=en',
'displayMessage' => '',
'debug' => "'false'",
'promptPhpErrors' => false,
'reloadQuerywindow' => ['db' => '', 'table' => '', 'sql_query' => ''],
'params' => $header->getJsParams(),
],
json_decode($body, true),
);
(new ReflectionProperty(ResponseRenderer::class, 'instance'))->setValue(null, null);
}
}

View File

@ -16,6 +16,7 @@ use PhpMyAdmin\Config;
use PhpMyAdmin\ConfigStorage\Relation;
use PhpMyAdmin\Console;
use PhpMyAdmin\DatabaseInterface;
use PhpMyAdmin\Error\ErrorHandler;
use PhpMyAdmin\Footer;
use PhpMyAdmin\Header;
use PhpMyAdmin\Http\Factory\ResponseFactory;
@ -46,24 +47,25 @@ class ResponseRenderer extends \PhpMyAdmin\ResponseRenderer
*/
public function __construct()
{
$this->isSuccess = true;
$this->isAjax = false;
$GLOBALS['lang'] = 'en';
$this->template = new Template();
$this->config = Config::getInstance();
$this->config->selectedServer['pmadb'] = 'phpmyadmin';
$config = Config::getInstance();
$config->selectedServer['pmadb'] = 'phpmyadmin';
$template = new Template($config);
$dummyDbi = new DbiDummy();
$dummyDbi->addSelectDb('phpmyadmin');
$dbi = new DatabaseInterface($dummyDbi);
$relation = new Relation($dbi);
$this->header = new Header(
$this->template,
new Console($relation, $this->template, new BookmarkRepository($dbi, $relation)),
$this->config,
$console = new Console($relation, $template, new BookmarkRepository($dbi, $relation));
parent::__construct(
$config,
$template,
new Header($template, $console, $config),
new Footer($template, $config),
ErrorHandler::getInstance(),
$dbi,
ResponseFactory::create(),
);
$this->footer = new Footer($this->template, $this->config);
$this->response = ResponseFactory::create()->createResponse();
}
/**