Extract schema export from schema plugins

Moves the response handling to the SchemaExportController.

Signed-off-by: Maurício Meneghini Fauth <mauricio@fauth.dev>
This commit is contained in:
Maurício Meneghini Fauth 2022-11-11 14:26:20 -03:00
parent 8b61402871
commit 32d06ae22e
No known key found for this signature in database
GPG Key ID: 6A16FD38AFC89CC8
22 changed files with 157 additions and 181 deletions

View File

@ -4,16 +4,18 @@ declare(strict_types=1);
namespace PhpMyAdmin\Controllers;
use PhpMyAdmin\Core;
use PhpMyAdmin\Dbal\DatabaseName;
use PhpMyAdmin\Exceptions\ExportException;
use PhpMyAdmin\Export;
use PhpMyAdmin\Html\MySQLDocumentation;
use PhpMyAdmin\Http\ServerRequest;
use PhpMyAdmin\Message;
use PhpMyAdmin\ResponseRenderer;
use RuntimeException;
use function __;
use function is_string;
use function mb_strlen;
/**
* Schema export handler
@ -51,10 +53,20 @@ class SchemaExportController
* Include the appropriate Schema Class depending on $exportType, default is PDF.
*/
try {
$this->export->processExportSchema($db, $exportType);
} catch (RuntimeException $exception) {
$exportInfo = $this->export->getExportSchemaInfo($db, $exportType);
} catch (ExportException $exception) {
$this->response->setRequestStatus(false);
$this->response->addHTML(Message::error($exception->getMessage())->getDisplay());
return;
}
$this->response->disable();
Core::downloadHeader(
$exportInfo['fileName'],
$exportInfo['mediaType'],
mb_strlen($exportInfo['fileData'], '8bit')
);
echo $exportInfo['fileData'];
}
}

View File

@ -11,9 +11,9 @@ use PhpMyAdmin\Controllers\Database\ExportController as DatabaseExportController
use PhpMyAdmin\Controllers\Server\ExportController as ServerExportController;
use PhpMyAdmin\Controllers\Table\ExportController as TableExportController;
use PhpMyAdmin\Dbal\DatabaseName;
use PhpMyAdmin\Exceptions\ExportException;
use PhpMyAdmin\Plugins\ExportPlugin;
use PhpMyAdmin\Plugins\SchemaPlugin;
use RuntimeException;
use function __;
use function array_filter;
@ -1240,9 +1240,13 @@ class Export
* get all the export options and verify
* call and include the appropriate Schema Class depending on $export_type
*
* @param non-empty-string $exportType format of the export
* @param non-empty-string $exportType
*
* @return array{fileName: non-empty-string, mediaType: non-empty-string, fileData: string}
*
* @throws ExportException
*/
public function processExportSchema(DatabaseName $db, string $exportType): void
public function getExportSchemaInfo(DatabaseName $db, string $exportType): array
{
/**
* default is PDF, otherwise validate it's only letters a-z
@ -1257,11 +1261,12 @@ class Export
// Check schema export type
if ($exportPlugin === null) {
throw new RuntimeException(__('Bad type!'));
throw new ExportException(__('Bad type!'));
}
$this->dbi->selectDb($db);
$exportPlugin->exportSchema($db->getName());
return $exportPlugin->getExportInfo($db);
}
private function getHTMLForRefreshButton(string $exportType): string

View File

@ -13,7 +13,6 @@ use TCPDF_FONTS;
use function __;
use function count;
use function strlen;
use function strtr;
/**
@ -137,21 +136,4 @@ class Pdf extends TCPDF
)->getDisplay();
exit;
}
/**
* Sends file as a download to user.
*
* @param string $filename file name
*/
public function download($filename): void
{
$pdfData = $this->getPDFData();
ResponseRenderer::getInstance()->disable();
Core::downloadHeader(
$filename,
'application/pdf',
strlen($pdfData)
);
echo $pdfData;
}
}

View File

@ -7,13 +7,9 @@ declare(strict_types=1);
namespace PhpMyAdmin\Plugins\Schema\Dia;
use PhpMyAdmin\Core;
use PhpMyAdmin\ResponseRenderer;
use XMLWriter;
use function ob_end_clean;
use function ob_get_clean;
use function strlen;
use function is_string;
/**
* This Class inherits the XMLwriter class and
@ -157,26 +153,10 @@ class Dia extends XMLWriter
$this->endDocument();
}
/**
* Output Dia Document for download
*
* @see XMLWriter::flush()
*
* @param string $fileName name of the dia document
*/
public function showOutput($fileName): void
public function getOutputData(): string
{
if (ob_get_clean()) {
ob_end_clean();
}
$data = $this->flush();
$output = $this->flush();
ResponseRenderer::getInstance()->disable();
Core::downloadHeader(
$fileName,
'application/x-dia-diagram',
strlen($output)
);
print $output;
return is_string($data) ? $data : '';
}
}

View File

@ -146,11 +146,11 @@ class DiaRelationSchema extends ExportRelationSchema
}
/**
* Output Dia Document for download
* @return array{fileName: non-empty-string, fileData: string}
*/
public function showOutput(): void
public function getExportInfo(): array
{
$this->diagram->showOutput($this->getFileName('.dia'));
return ['fileName' => $this->getFileName('.dia'), 'fileData' => $this->diagram->getOutputData()];
}
/**

View File

@ -7,11 +7,6 @@ declare(strict_types=1);
namespace PhpMyAdmin\Plugins\Schema\Eps;
use PhpMyAdmin\Core;
use PhpMyAdmin\ResponseRenderer;
use function strlen;
/**
* This Class is EPS Library and
* helps in developing structure of EPS Schema Export
@ -234,24 +229,8 @@ class Eps
$this->stringCommands .= "showpage \n";
}
/**
* Output EPS Document for download
*
* @param string $fileName name of the eps document
*/
public function showOutput($fileName): void
public function getOutputData(): string
{
// if(ob_get_clean()){
//ob_end_clean();
//}
$output = $this->stringCommands;
ResponseRenderer::getInstance()
->disable();
Core::downloadHeader(
$fileName,
'image/x-eps',
strlen($output)
);
print $output;
return $this->stringCommands;
}
}

View File

@ -153,11 +153,11 @@ class EpsRelationSchema extends ExportRelationSchema
}
/**
* Output Eps Document for download
* @return array{fileName: non-empty-string, fileData: string}
*/
public function showOutput(): void
public function getExportInfo(): array
{
$this->diagram->showOutput($this->getFileName('.eps'));
return ['fileName' => $this->getFileName('.eps'), 'fileData' => $this->diagram->getOutputData()];
}
/**

View File

@ -237,13 +237,11 @@ class ExportRelationSchema
}
/**
* Returns the file name
* @param non-empty-string $extension
*
* @param string $extension file extension
*
* @return string file name
* @return non-empty-string
*/
protected function getFileName($extension): string
protected function getFileName(string $extension): string
{
$pdfFeature = $this->relation->getRelationParameters()->pdfFeature;

View File

@ -14,6 +14,7 @@ use PhpMyAdmin\Util;
use function __;
use function count;
use function getcwd;
use function is_string;
use function max;
use function mb_ord;
use function str_replace;
@ -428,4 +429,12 @@ class Pdf extends PdfLib
{
$this->offline = $value;
}
public function getOutputData(): string
{
/** @var mixed $data */
$data = $this->getPDFData();
return is_string($data) ? $data : '';
}
}

View File

@ -316,11 +316,11 @@ class PdfRelationSchema extends ExportRelationSchema
}
/**
* Output Pdf Document for download
* @return array{fileName: non-empty-string, fileData: string}
*/
public function showOutput(): void
public function getExportInfo(): array
{
$this->diagram->download($this->getFileName('.pdf'));
return ['fileName' => $this->getFileName('.pdf'), 'fileData' => $this->diagram->getOutputData()];
}
/**

View File

@ -7,6 +7,7 @@ declare(strict_types=1);
namespace PhpMyAdmin\Plugins\Schema;
use PhpMyAdmin\Dbal\DatabaseName;
use PhpMyAdmin\Plugins\Schema\Dia\DiaRelationSchema;
use PhpMyAdmin\Plugins\SchemaPlugin;
use PhpMyAdmin\Properties\Options\Groups\OptionsPropertyMainGroup;
@ -78,15 +79,17 @@ class SchemaDia extends SchemaPlugin
}
/**
* Exports the schema into DIA format.
*
* @param string $db database name
* @return array{fileName: non-empty-string, mediaType: non-empty-string, fileData: string}
*/
public function exportSchema($db): bool
public function getExportInfo(DatabaseName $db): array
{
$export = new DiaRelationSchema($db);
$export->showOutput();
$export = new DiaRelationSchema($db->getName());
$exportInfo = $export->getExportInfo();
return true;
return [
'fileName' => $exportInfo['fileName'],
'mediaType' => 'application/x-dia-diagram',
'fileData' => $exportInfo['fileData'],
];
}
}

View File

@ -7,6 +7,7 @@ declare(strict_types=1);
namespace PhpMyAdmin\Plugins\Schema;
use PhpMyAdmin\Dbal\DatabaseName;
use PhpMyAdmin\Plugins\Schema\Eps\EpsRelationSchema;
use PhpMyAdmin\Plugins\SchemaPlugin;
use PhpMyAdmin\Properties\Options\Groups\OptionsPropertyMainGroup;
@ -79,15 +80,17 @@ class SchemaEps extends SchemaPlugin
}
/**
* Exports the schema into EPS format.
*
* @param string $db database name
* @return array{fileName: non-empty-string, mediaType: non-empty-string, fileData: string}
*/
public function exportSchema($db): bool
public function getExportInfo(DatabaseName $db): array
{
$export = new EpsRelationSchema($db);
$export->showOutput();
$export = new EpsRelationSchema($db->getName());
$exportInfo = $export->getExportInfo();
return true;
return [
'fileName' => $exportInfo['fileName'],
'mediaType' => 'image/x-eps',
'fileData' => $exportInfo['fileData'],
];
}
}

View File

@ -7,6 +7,7 @@ declare(strict_types=1);
namespace PhpMyAdmin\Plugins\Schema;
use PhpMyAdmin\Dbal\DatabaseName;
use PhpMyAdmin\Plugins\Schema\Pdf\PdfRelationSchema;
use PhpMyAdmin\Plugins\SchemaPlugin;
use PhpMyAdmin\Properties\Options\Groups\OptionsPropertyMainGroup;
@ -113,16 +114,18 @@ class SchemaPdf extends SchemaPlugin
}
/**
* Exports the schema into PDF format.
*
* @param string $db database name
* @return array{fileName: non-empty-string, mediaType: non-empty-string, fileData: string}
*/
public function exportSchema($db): bool
public function getExportInfo(DatabaseName $db): array
{
$export = new PdfRelationSchema($db);
$export->showOutput();
$export = new PdfRelationSchema($db->getName());
$exportInfo = $export->getExportInfo();
return true;
return [
'fileName' => $exportInfo['fileName'],
'mediaType' => 'application/pdf',
'fileData' => $exportInfo['fileData'],
];
}
public static function isAvailable(): bool

View File

@ -7,6 +7,7 @@ declare(strict_types=1);
namespace PhpMyAdmin\Plugins\Schema;
use PhpMyAdmin\Dbal\DatabaseName;
use PhpMyAdmin\Plugins\Schema\Svg\SvgRelationSchema;
use PhpMyAdmin\Plugins\SchemaPlugin;
use PhpMyAdmin\Properties\Options\Groups\OptionsPropertyMainGroup;
@ -66,15 +67,17 @@ class SchemaSvg extends SchemaPlugin
}
/**
* Exports the schema into SVG format.
*
* @param string $db database name
* @return array{fileName: non-empty-string, mediaType: non-empty-string, fileData: string}
*/
public function exportSchema($db): bool
public function getExportInfo(DatabaseName $db): array
{
$export = new SvgRelationSchema($db);
$export->showOutput();
$export = new SvgRelationSchema($db->getName());
$exportInfo = $export->getExportInfo();
return true;
return [
'fileName' => $exportInfo['fileName'],
'mediaType' => 'image/svg+xml',
'fileData' => $exportInfo['fileData'],
];
}
}

View File

@ -7,14 +7,12 @@ declare(strict_types=1);
namespace PhpMyAdmin\Plugins\Schema\Svg;
use PhpMyAdmin\Core;
use PhpMyAdmin\ResponseRenderer;
use XMLWriter;
use function intval;
use function is_int;
use function is_string;
use function sprintf;
use function strlen;
/**
* This Class inherits the XMLwriter class and
@ -164,29 +162,11 @@ class Svg extends XMLWriter
$this->endDocument();
}
/**
* output RelationStatsSvg Document
*
* svg document prompted to the user for download
* RelationStatsSvg document saved in .svg extension and can be
* easily changeable by using any svg IDE
*
* @see XMLWriter::startElement()
* @see XMLWriter::writeAttribute()
*
* @param string $fileName file name
*/
public function showOutput($fileName): void
public function getOutputData(): string
{
//ob_get_clean();
$output = $this->flush();
ResponseRenderer::getInstance()->disable();
Core::downloadHeader(
$fileName,
'image/svg+xml',
strlen($output)
);
print $output;
$data = $this->flush();
return is_string($data) ? $data : '';
}
/**

View File

@ -176,11 +176,11 @@ class SvgRelationSchema extends ExportRelationSchema
}
/**
* Output RelationStatsSvg Document for download
* @return array{fileName: non-empty-string, fileData: string}
*/
public function showOutput(): void
public function getExportInfo(): array
{
$this->diagram->showOutput($this->getFileName('.svg'));
return ['fileName' => $this->getFileName('.svg'), 'fileData' => $this->diagram->getOutputData()];
}
/**

View File

@ -7,6 +7,7 @@ declare(strict_types=1);
namespace PhpMyAdmin\Plugins;
use PhpMyAdmin\Dbal\DatabaseName;
use PhpMyAdmin\Properties\Options\Groups\OptionsPropertyMainGroup;
use PhpMyAdmin\Properties\Options\Items\BoolPropertyItem;
use PhpMyAdmin\Properties\Plugins\PluginPropertyItem;
@ -58,11 +59,9 @@ abstract class SchemaPlugin implements Plugin
abstract protected function setProperties(): SchemaPluginProperties;
/**
* Exports the schema into the specified format.
*
* @param string $db database name
* @return array{fileName: non-empty-string, mediaType: non-empty-string, fileData: string}
*/
abstract public function exportSchema($db): bool;
abstract public function getExportInfo(DatabaseName $db): array;
/**
* Adds export options common to all plugins.

View File

@ -69,7 +69,7 @@ class ResponseRenderer
*
* @var bool
*/
private $isDisabled;
protected $isDisabled;
/**
* Whether there were any errors during the processing of the request
* Only used for ajax responses

View File

@ -6330,16 +6330,6 @@ parameters:
count: 1
path: libraries/classes/Plugins/ImportPlugin.php
-
message: "#^Parameter \\#1 \\$string of function strlen expects string, mixed given\\.$#"
count: 1
path: libraries/classes/Plugins/Schema/Dia/Dia.php
-
message: "#^Parameter mixed of print cannot be converted to string\\.$#"
count: 1
path: libraries/classes/Plugins/Schema/Dia/Dia.php
-
message: "#^Binary operation \"\\+\" between int\\|string\\|false and 12 results in an error\\.$#"
count: 4
@ -6510,16 +6500,6 @@ parameters:
count: 3
path: libraries/classes/Plugins/Schema/Svg/Svg.php
-
message: "#^Parameter \\#1 \\$string of function strlen expects string, mixed given\\.$#"
count: 1
path: libraries/classes/Plugins/Schema/Svg/Svg.php
-
message: "#^Parameter mixed of print cannot be converted to string\\.$#"
count: 1
path: libraries/classes/Plugins/Schema/Svg/Svg.php
-
message: "#^Parameter \\#1 \\$table of method PhpMyAdmin\\\\Plugins\\\\Schema\\\\Svg\\\\SvgRelationSchema\\:\\:setMinMax\\(\\) expects PhpMyAdmin\\\\Plugins\\\\Schema\\\\Svg\\\\TableStatsSvg, PhpMyAdmin\\\\Plugins\\\\Schema\\\\Dia\\\\TableStatsDia\\|PhpMyAdmin\\\\Plugins\\\\Schema\\\\Eps\\\\TableStatsEps\\|PhpMyAdmin\\\\Plugins\\\\Schema\\\\Pdf\\\\TableStatsPdf\\|PhpMyAdmin\\\\Plugins\\\\Schema\\\\Svg\\\\TableStatsSvg given\\.$#"
count: 1

View File

@ -9267,8 +9267,7 @@
</PossiblyInvalidArrayOffset>
</file>
<file src="libraries/classes/Pdf.php">
<MixedArgument occurrences="4">
<code>$pdfData</code>
<MixedArgument occurrences="3">
<code>$this-&gt;CurrentFont</code>
<code>$this-&gt;pages</code>
<code>$this-&gt;pages[$n]</code>
@ -9283,9 +9282,6 @@
<code>$this-&gt;footerset[$this-&gt;page]</code>
<code>$this-&gt;footerset[$this-&gt;page]</code>
</MixedArrayOffset>
<MixedAssignment occurrences="1">
<code>$pdfData</code>
</MixedAssignment>
<ParamNameMismatch occurrences="1">
<code>$error_message</code>
</ParamNameMismatch>
@ -10990,11 +10986,6 @@
<code>(string) $currentDb</code>
</RedundantCastGivenDocblockType>
</file>
<file src="libraries/classes/Plugins/Schema/Dia/Dia.php">
<PossiblyInvalidArgument occurrences="1">
<code>$output</code>
</PossiblyInvalidArgument>
</file>
<file src="libraries/classes/Plugins/Schema/Dia/DiaRelationSchema.php">
<MixedArgument occurrences="5">
<code>$one_field</code>
@ -11615,9 +11606,6 @@
<code>is_int($height)</code>
<code>is_int($width)</code>
</DocblockTypeContradiction>
<PossiblyInvalidArgument occurrences="1">
<code>$output</code>
</PossiblyInvalidArgument>
<RedundantCastGivenDocblockType occurrences="3">
<code>(string) $styles</code>
<code>(string) $styles</code>

View File

@ -0,0 +1,46 @@
<?php
declare(strict_types=1);
namespace PhpMyAdmin\Tests\Controllers;
use PhpMyAdmin\Controllers\SchemaExportController;
use PhpMyAdmin\Export;
use PhpMyAdmin\Http\ServerRequest;
use PhpMyAdmin\Tests\AbstractTestCase;
use PhpMyAdmin\Tests\Stubs\ResponseRenderer;
/**
* @covers \PhpMyAdmin\Controllers\SchemaExportController
*/
class SchemaExportControllerTest extends AbstractTestCase
{
/**
* @runInSeparateProcess
*/
public function testExport(): void
{
$GLOBALS['dbi'] = $this->createDatabaseInterface();
$request = $this->createStub(ServerRequest::class);
$request->method('getParsedBodyParam')->willReturnMap([
['db', null, 'test_db'],
['export_type', null, 'svg'],
]);
$export = $this->createStub(Export::class);
$export->method('getExportSchemaInfo')->willReturn([
'fileName' => 'file.svg',
'mediaType' => 'image/svg+xml',
'fileData' => 'file data',
]);
$response = new ResponseRenderer();
$controller = new SchemaExportController($export, $response);
$controller($request);
$output = $this->getActualOutputForAssertion();
$this->assertSame('file data', $output);
$this->assertTrue($response->isDisabled());
$this->assertSame('', $response->getHTMLResult());
$this->assertSame([], $response->getJSONResult());
}
}

View File

@ -46,6 +46,7 @@ class ResponseRenderer extends \PhpMyAdmin\ResponseRenderer
$this->htmlString = '';
$this->json = [];
$this->isAjax = false;
$this->isDisabled = false;
$GLOBALS['lang'] = 'en';
$GLOBALS['server'] = $GLOBALS['server'] ?? 1;
@ -173,4 +174,9 @@ class ResponseRenderer extends \PhpMyAdmin\ResponseRenderer
{
return $this->responseCode;
}
public function isDisabled(): bool
{
return $this->isDisabled;
}
}