commit
b89ee4e4fc
@ -264,6 +264,13 @@ rendered, for example in following document:
|
||||
|
||||
\end{document}
|
||||
|
||||
TOON
|
||||
----
|
||||
|
||||
Data can be exported to TOON `(Token-Oriented Object Notation) <https://en.wikipedia.org/wiki/Token-Oriented_Object_Notation>`_,
|
||||
which is a text-based data format. It encodes the JSON data model in a compact way.
|
||||
TOON is designed to reduce token usage in LLM prompts while staying human-readable.
|
||||
|
||||
MediaWiki
|
||||
---------
|
||||
|
||||
|
||||
@ -783,13 +783,13 @@ parameters:
|
||||
-
|
||||
message: '#^Cannot cast mixed to int\.$#'
|
||||
identifier: cast.int
|
||||
count: 2
|
||||
count: 3
|
||||
path: src/Config/Settings/Export.php
|
||||
|
||||
-
|
||||
message: '#^Cannot cast mixed to string\.$#'
|
||||
identifier: cast.string
|
||||
count: 23
|
||||
count: 24
|
||||
path: src/Config/Settings/Export.php
|
||||
|
||||
-
|
||||
@ -5812,7 +5812,7 @@ parameters:
|
||||
path: src/Export/Options.php
|
||||
|
||||
-
|
||||
message: '#^Only booleans are allowed in &&, bool\|int\<0, max\>\|string given on the right side\.$#'
|
||||
message: '#^Only booleans are allowed in &&, bool\|int\|string given on the right side\.$#'
|
||||
identifier: booleanAnd.rightNotBoolean
|
||||
count: 1
|
||||
path: src/Export/Options.php
|
||||
@ -8901,6 +8901,21 @@ parameters:
|
||||
count: 2
|
||||
path: src/Plugins/Export/ExportTexytext.php
|
||||
|
||||
-
|
||||
message: '''
|
||||
#^Call to deprecated method getInstance\(\) of class PhpMyAdmin\\Dbal\\DatabaseInterface\:
|
||||
Use dependency injection instead\.$#
|
||||
'''
|
||||
identifier: staticMethod.deprecated
|
||||
count: 2
|
||||
path: src/Plugins/Export/ExportToon.php
|
||||
|
||||
-
|
||||
message: '#^Cannot cast mixed to int\.$#'
|
||||
identifier: cast.int
|
||||
count: 1
|
||||
path: src/Plugins/Export/ExportToon.php
|
||||
|
||||
-
|
||||
message: '#^Construct empty\(\) is not allowed\. Use more strict comparison\.$#'
|
||||
identifier: empty.notAllowed
|
||||
|
||||
@ -5997,6 +5997,20 @@
|
||||
<code><![CDATA[$mimeMap]]></code>
|
||||
</PossiblyUndefinedVariable>
|
||||
</file>
|
||||
<file src="src/Plugins/Export/ExportToon.php">
|
||||
<DeprecatedMethod>
|
||||
<code><![CDATA[DatabaseInterface::getInstance()]]></code>
|
||||
<code><![CDATA[DatabaseInterface::getInstance()]]></code>
|
||||
</DeprecatedMethod>
|
||||
<RedundantCondition>
|
||||
<code><![CDATA[$exportConfig->toon_indent]]></code>
|
||||
<code><![CDATA[$exportConfig->toon_separator]]></code>
|
||||
</RedundantCondition>
|
||||
<TypeDoesNotContainType>
|
||||
<code><![CDATA[$this->indent]]></code>
|
||||
<code><![CDATA[$this->separator]]></code>
|
||||
</TypeDoesNotContainType>
|
||||
</file>
|
||||
<file src="src/Plugins/Export/ExportXml.php">
|
||||
<InvalidArgument>
|
||||
<code><![CDATA[$events]]></code>
|
||||
|
||||
@ -55,6 +55,9 @@ use function in_array;
|
||||
* csv_escaped: string,
|
||||
* csv_terminated: string,
|
||||
* csv_removeCRLF: bool,
|
||||
* toon_indent: int,
|
||||
* toon_separator: string,
|
||||
* toon_structure_or_data: StructureOrDataType,
|
||||
* excel_columns: bool,
|
||||
* excel_null: string,
|
||||
* excel_edition: 'mac_excel2003'|'mac_excel2008'|'win',
|
||||
@ -442,6 +445,29 @@ final class Export
|
||||
*/
|
||||
public bool $csv_removeCRLF;
|
||||
|
||||
/**
|
||||
* ```php
|
||||
* $cfg['Export']['toon_indent'] = 2;
|
||||
* ```
|
||||
*/
|
||||
public int $toon_indent;
|
||||
|
||||
/**
|
||||
* ```php
|
||||
* $cfg['Export']['toon_separator'] = ',';
|
||||
* ```
|
||||
*/
|
||||
public string $toon_separator;
|
||||
|
||||
/**
|
||||
* ```php
|
||||
* $cfg['Export']['toon_structure_or_data'] = 'structure_and_data';
|
||||
* ```
|
||||
*
|
||||
* @psalm-var StructureOrDataType
|
||||
*/
|
||||
public string $toon_structure_or_data;
|
||||
|
||||
/**
|
||||
* ```php
|
||||
* $cfg['Export']['excel_columns'] = true;
|
||||
@ -1031,6 +1057,9 @@ final class Export
|
||||
$this->csv_escaped = $this->setCsvEscaped($export);
|
||||
$this->csv_terminated = $this->setCsvTerminated($export);
|
||||
$this->csv_removeCRLF = $this->setCsvRemoveCRLF($export);
|
||||
$this->toon_indent = $this->setToonIndent($export);
|
||||
$this->toon_separator = $this->setToonSeparator($export);
|
||||
$this->toon_structure_or_data = $this->setToonStructureOrData($export);
|
||||
$this->excel_columns = $this->setExcelColumns($export);
|
||||
$this->excel_null = $this->setExcelNull($export);
|
||||
$this->excel_edition = $this->setExcelEdition($export);
|
||||
@ -1146,6 +1175,9 @@ final class Export
|
||||
'csv_escaped' => $this->csv_escaped,
|
||||
'csv_terminated' => $this->csv_terminated,
|
||||
'csv_removeCRLF' => $this->csv_removeCRLF,
|
||||
'toon_indent' => $this->toon_indent,
|
||||
'toon_separator' => $this->toon_separator,
|
||||
'toon_structure_or_data' => $this->toon_structure_or_data,
|
||||
'excel_columns' => $this->excel_columns,
|
||||
'excel_null' => $this->excel_null,
|
||||
'excel_edition' => $this->excel_edition,
|
||||
@ -1680,6 +1712,43 @@ final class Export
|
||||
return (bool) $export['csv_removeCRLF'];
|
||||
}
|
||||
|
||||
/** @param array<int|string, mixed> $export */
|
||||
private function setToonIndent(array $export): int
|
||||
{
|
||||
if (! isset($export['toon_indent'])) {
|
||||
return 2;
|
||||
}
|
||||
|
||||
return (int) $export['toon_indent'];
|
||||
}
|
||||
|
||||
/** @param array<int|string, mixed> $export */
|
||||
private function setToonSeparator(array $export): string
|
||||
{
|
||||
if (! isset($export['toon_separator'])) {
|
||||
return ',';
|
||||
}
|
||||
|
||||
return (string) $export['toon_separator'];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<int|string, mixed> $export
|
||||
*
|
||||
* @psalm-return StructureOrDataType
|
||||
*/
|
||||
private function setToonStructureOrData(array $export): string
|
||||
{
|
||||
if (
|
||||
! isset($export['toon_structure_or_data'])
|
||||
|| ! in_array($export['toon_structure_or_data'], ['structure', 'data'], true)
|
||||
) {
|
||||
return 'structure_and_data';
|
||||
}
|
||||
|
||||
return $export['toon_structure_or_data'];
|
||||
}
|
||||
|
||||
/** @param array<int|string, mixed> $export */
|
||||
private function setExcelColumns(array $export): bool
|
||||
{
|
||||
|
||||
228
src/Plugins/Export/ExportToon.php
Normal file
228
src/Plugins/Export/ExportToon.php
Normal file
@ -0,0 +1,228 @@
|
||||
<?php
|
||||
/**
|
||||
* Export to TOON text.
|
||||
*/
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace PhpMyAdmin\Plugins\Export;
|
||||
|
||||
use PhpMyAdmin\Config\Settings\Export;
|
||||
use PhpMyAdmin\Dbal\DatabaseInterface;
|
||||
use PhpMyAdmin\Export\StructureOrData;
|
||||
use PhpMyAdmin\Http\ServerRequest;
|
||||
use PhpMyAdmin\Plugins\ExportPlugin;
|
||||
use PhpMyAdmin\Properties\Options\Groups\OptionsPropertyMainGroup;
|
||||
use PhpMyAdmin\Properties\Options\Groups\OptionsPropertyRootGroup;
|
||||
use PhpMyAdmin\Properties\Options\Items\HiddenPropertyItem;
|
||||
use PhpMyAdmin\Properties\Options\Items\TextPropertyItem;
|
||||
use PhpMyAdmin\Properties\Plugins\ExportPluginProperties;
|
||||
|
||||
use function __;
|
||||
use function array_key_last;
|
||||
use function is_int;
|
||||
use function is_string;
|
||||
use function sprintf;
|
||||
use function str_repeat;
|
||||
use function str_replace;
|
||||
|
||||
/**
|
||||
* Handles the export for the TOON format
|
||||
*/
|
||||
class ExportToon extends ExportPlugin
|
||||
{
|
||||
private int $indent = 2;
|
||||
private string $separator = ',';
|
||||
|
||||
/** @psalm-return non-empty-lowercase-string */
|
||||
public function getName(): string
|
||||
{
|
||||
return 'toon';
|
||||
}
|
||||
|
||||
protected function setProperties(): ExportPluginProperties
|
||||
{
|
||||
$exportPluginProperties = new ExportPluginProperties();
|
||||
$exportPluginProperties->setText('TOON');
|
||||
$exportPluginProperties->setExtension('toon');
|
||||
$exportPluginProperties->setMimeType('text/toon');
|
||||
$exportPluginProperties->setForceFile(true);
|
||||
$exportPluginProperties->setOptionsText(__('Options'));
|
||||
|
||||
// create the root group that will be the options field for
|
||||
// $exportPluginProperties
|
||||
// this will be shown as "Format specific options"
|
||||
$exportSpecificOptions = new OptionsPropertyRootGroup('Format Specific Options');
|
||||
|
||||
// general options main group
|
||||
$generalOptions = new OptionsPropertyMainGroup('general_opts');
|
||||
// create leaf items and add them to the group
|
||||
$leaf = new TextPropertyItem(
|
||||
'separator',
|
||||
__('Columns separated with:'),
|
||||
);
|
||||
$generalOptions->addProperty($leaf);
|
||||
$leaf = new TextPropertyItem(
|
||||
'indent',
|
||||
__('Indentation:'),
|
||||
);
|
||||
$generalOptions->addProperty($leaf);
|
||||
// create primary items and add them to the group
|
||||
$leaf = new HiddenPropertyItem('structure_or_data');
|
||||
$generalOptions->addProperty($leaf);
|
||||
// add the main group to the root group
|
||||
$exportSpecificOptions->addProperty($generalOptions);
|
||||
|
||||
// set the options for the export plugin property item
|
||||
$exportPluginProperties->setOptions($exportSpecificOptions);
|
||||
|
||||
return $exportPluginProperties;
|
||||
}
|
||||
|
||||
/**
|
||||
* Outputs the content of a table in JSON format
|
||||
*
|
||||
* @param string $db database name
|
||||
* @param string $table table name
|
||||
* @param string $sqlQuery SQL query for obtaining data
|
||||
* @param mixed[] $aliases Aliases of db/table/columns
|
||||
*/
|
||||
public function exportData(
|
||||
string $db,
|
||||
string $table,
|
||||
string $sqlQuery,
|
||||
array $aliases = [],
|
||||
): void {
|
||||
$dbAlias = $this->getDbAlias($aliases, $db);
|
||||
$tableAlias = $this->getTableAlias($aliases, $db, $table);
|
||||
$dbi = DatabaseInterface::getInstance();
|
||||
$result = $dbi->query($sqlQuery);
|
||||
|
||||
$columnsCnt = $result->numFields();
|
||||
$rowsCnt = $result->numRows();
|
||||
$fieldsMeta = $dbi->getFieldsMeta($result);
|
||||
|
||||
$columns = [];
|
||||
foreach ($fieldsMeta as $i => $field) {
|
||||
$colAs = $this->getColumnAlias($aliases, $db, $table, $field->name);
|
||||
|
||||
$columns[$i] = $colAs;
|
||||
}
|
||||
|
||||
$buffer = sprintf(
|
||||
'%s.%s[%s%s]{',
|
||||
$dbAlias,
|
||||
$tableAlias,
|
||||
$rowsCnt,
|
||||
$this->separator !== ',' ? $this->separator : '',
|
||||
);
|
||||
foreach ($columns as $index => $column) {
|
||||
$buffer .= $column;
|
||||
|
||||
// phpcs:ignore SlevomatCodingStandard.ControlStructures.EarlyExit.EarlyExitNotUsed
|
||||
if ($index !== array_key_last($columns)) {
|
||||
$buffer .= $this->separator;
|
||||
}
|
||||
}
|
||||
|
||||
$buffer .= "}:\n";
|
||||
|
||||
$this->outputHandler->addLine($buffer);
|
||||
|
||||
$insertedLines = 0;
|
||||
while ($row = $result->fetchRow()) {
|
||||
$buffer = '';
|
||||
|
||||
foreach ($row as $index => $col) {
|
||||
if ($index === 0) {
|
||||
$buffer .= str_repeat(' ', $this->indent);
|
||||
}
|
||||
|
||||
if ($col === null) {
|
||||
$buffer .= 'null';
|
||||
continue;
|
||||
}
|
||||
|
||||
$buffer .= $col;
|
||||
|
||||
// phpcs:ignore SlevomatCodingStandard.ControlStructures.EarlyExit.EarlyExitNotUsed
|
||||
if ($index !== $columnsCnt - 1) {
|
||||
$buffer .= $this->separator;
|
||||
}
|
||||
}
|
||||
|
||||
$insertedLines++;
|
||||
$buffer .= $insertedLines === $rowsCnt ? "\n\n" : "\n";
|
||||
$this->outputHandler->addLine($buffer);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Outputs result raw query in TOON format
|
||||
*
|
||||
* @param string $db the database where the query is executed
|
||||
* @param string $sqlQuery the rawquery to output
|
||||
*/
|
||||
public function exportRawQuery(string $db, string $sqlQuery): void
|
||||
{
|
||||
if ($db !== '') {
|
||||
DatabaseInterface::getInstance()->selectDb($db);
|
||||
}
|
||||
|
||||
$this->exportData($db, '', $sqlQuery);
|
||||
}
|
||||
|
||||
private function setupExportConfiguration(): void
|
||||
{
|
||||
$this->separator = str_replace('\\t', "\011", $this->separator);
|
||||
}
|
||||
|
||||
public function setExportOptions(ServerRequest $request, Export $exportConfig): void
|
||||
{
|
||||
// phpcs:disable Squiz.NamingConventions.ValidVariableName.MemberNotCamelCaps
|
||||
$this->structureOrData = $this->setStructureOrData(
|
||||
$request->getParsedBodyParam('toon_structure_or_data'),
|
||||
$exportConfig->toon_structure_or_data,
|
||||
StructureOrData::StructureAndData,
|
||||
);
|
||||
|
||||
$this->separator = $this->setStringValue(
|
||||
$request->getParsedBodyParam('toon_separator'),
|
||||
$exportConfig->toon_separator ?? $this->separator,
|
||||
);
|
||||
|
||||
$this->indent = $this->setIntValue(
|
||||
(int) $request->getParsedBodyParam('toon_indent'),
|
||||
$exportConfig->toon_indent ?? $this->indent,
|
||||
);
|
||||
// phpcs:enable Squiz.NamingConventions.ValidVariableName.MemberNotCamelCaps
|
||||
|
||||
$this->setupExportConfiguration();
|
||||
}
|
||||
|
||||
private function setStringValue(mixed $fromRequest, mixed $fromConfig): string
|
||||
{
|
||||
if (is_string($fromRequest) && $fromRequest !== '') {
|
||||
return $fromRequest;
|
||||
}
|
||||
|
||||
if (is_string($fromConfig) && $fromConfig !== '') {
|
||||
return $fromConfig;
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
private function setIntValue(mixed $fromRequest, mixed $fromConfig): int
|
||||
{
|
||||
if (is_int($fromRequest)) {
|
||||
return $fromRequest;
|
||||
}
|
||||
|
||||
if (is_int($fromConfig)) {
|
||||
return $fromConfig;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
229
tests/unit/Plugins/Export/ExportToonTest.php
Normal file
229
tests/unit/Plugins/Export/ExportToonTest.php
Normal file
@ -0,0 +1,229 @@
|
||||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace PhpMyAdmin\Tests\Plugins\Export;
|
||||
|
||||
use PhpMyAdmin\Config;
|
||||
use PhpMyAdmin\Config\Settings\Export;
|
||||
use PhpMyAdmin\ConfigStorage\Relation;
|
||||
use PhpMyAdmin\Current;
|
||||
use PhpMyAdmin\Dbal\DatabaseInterface;
|
||||
use PhpMyAdmin\Export\OutputHandler;
|
||||
use PhpMyAdmin\Http\Factory\ServerRequestFactory;
|
||||
use PhpMyAdmin\Plugins\Export\ExportToon;
|
||||
use PhpMyAdmin\Plugins\ExportPlugin;
|
||||
use PhpMyAdmin\Plugins\ExportType;
|
||||
use PhpMyAdmin\Properties\Options\Groups\OptionsPropertyMainGroup;
|
||||
use PhpMyAdmin\Properties\Options\Groups\OptionsPropertyRootGroup;
|
||||
use PhpMyAdmin\Properties\Options\Items\HiddenPropertyItem;
|
||||
use PhpMyAdmin\Properties\Options\Items\TextPropertyItem;
|
||||
use PhpMyAdmin\Properties\Plugins\ExportPluginProperties;
|
||||
use PhpMyAdmin\Tests\AbstractTestCase;
|
||||
use PhpMyAdmin\Transformations;
|
||||
use PHPUnit\Framework\Attributes\CoversClass;
|
||||
use PHPUnit\Framework\Attributes\Medium;
|
||||
use ReflectionMethod;
|
||||
use ReflectionProperty;
|
||||
|
||||
use function ob_get_clean;
|
||||
use function ob_start;
|
||||
|
||||
#[CoversClass(ExportToon::class)]
|
||||
#[Medium]
|
||||
class ExportToonTest extends AbstractTestCase
|
||||
{
|
||||
protected function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
OutputHandler::$asFile = false;
|
||||
ExportPlugin::$exportType = ExportType::Table;
|
||||
ExportPlugin::$singleTable = false;
|
||||
Current::$database = '';
|
||||
Current::$table = '';
|
||||
Current::$lang = 'en';
|
||||
}
|
||||
|
||||
public function testSetProperties(): void
|
||||
{
|
||||
$exportToon = $this->getExportToon();
|
||||
|
||||
$method = new ReflectionMethod(ExportToon::class, 'setProperties');
|
||||
$method->invoke($exportToon, null);
|
||||
|
||||
$attrProperties = new ReflectionProperty(ExportToon::class, 'properties');
|
||||
$properties = $attrProperties->getValue($exportToon);
|
||||
|
||||
self::assertInstanceOf(ExportPluginProperties::class, $properties);
|
||||
|
||||
self::assertSame(
|
||||
'TOON',
|
||||
$properties->getText(),
|
||||
);
|
||||
|
||||
self::assertSame(
|
||||
'toon',
|
||||
$properties->getExtension(),
|
||||
);
|
||||
|
||||
self::assertSame(
|
||||
'text/toon',
|
||||
$properties->getMimeType(),
|
||||
);
|
||||
|
||||
self::assertSame(
|
||||
'Options',
|
||||
$properties->getOptionsText(),
|
||||
);
|
||||
|
||||
$options = $properties->getOptions();
|
||||
|
||||
self::assertInstanceOf(OptionsPropertyRootGroup::class, $options);
|
||||
|
||||
self::assertSame(
|
||||
'Format Specific Options',
|
||||
$options->getName(),
|
||||
);
|
||||
|
||||
$generalOptionsArray = $options->getProperties();
|
||||
$generalOptions = $generalOptionsArray->current();
|
||||
|
||||
self::assertInstanceOf(OptionsPropertyMainGroup::class, $generalOptions);
|
||||
|
||||
self::assertSame(
|
||||
'general_opts',
|
||||
$generalOptions->getName(),
|
||||
);
|
||||
|
||||
$generalProperties = $generalOptions->getProperties();
|
||||
|
||||
$property = $generalProperties->current();
|
||||
$generalProperties->next();
|
||||
|
||||
self::assertInstanceOf(TextPropertyItem::class, $property);
|
||||
|
||||
self::assertSame(
|
||||
'separator',
|
||||
$property->getName(),
|
||||
);
|
||||
|
||||
self::assertSame(
|
||||
'Columns separated with:',
|
||||
$property->getText(),
|
||||
);
|
||||
|
||||
$property = $generalProperties->current();
|
||||
$generalProperties->next();
|
||||
|
||||
self::assertInstanceOf(TextPropertyItem::class, $property);
|
||||
|
||||
self::assertSame(
|
||||
'indent',
|
||||
$property->getName(),
|
||||
);
|
||||
|
||||
self::assertSame(
|
||||
'Indentation:',
|
||||
$property->getText(),
|
||||
);
|
||||
|
||||
$property = $generalProperties->current();
|
||||
|
||||
self::assertInstanceOf(HiddenPropertyItem::class, $property);
|
||||
|
||||
self::assertSame(
|
||||
'structure_or_data',
|
||||
$property->getName(),
|
||||
);
|
||||
}
|
||||
|
||||
public function testExportHeader(): void
|
||||
{
|
||||
$exportToon = $this->getExportToon();
|
||||
$this->expectNotToPerformAssertions();
|
||||
$exportToon->exportHeader();
|
||||
}
|
||||
|
||||
public function testExportFooter(): void
|
||||
{
|
||||
$exportToon = $this->getExportToon();
|
||||
$this->expectNotToPerformAssertions();
|
||||
$exportToon->exportFooter();
|
||||
}
|
||||
|
||||
public function testExportDBHeader(): void
|
||||
{
|
||||
$exportToon = $this->getExportToon();
|
||||
$this->expectNotToPerformAssertions();
|
||||
$exportToon->exportDBHeader('testDB');
|
||||
}
|
||||
|
||||
public function testExportDBFooter(): void
|
||||
{
|
||||
$exportToon = $this->getExportToon();
|
||||
$this->expectNotToPerformAssertions();
|
||||
$exportToon->exportDBFooter('testDB');
|
||||
}
|
||||
|
||||
public function testExportDBCreate(): void
|
||||
{
|
||||
$exportToon = $this->getExportToon();
|
||||
$this->expectNotToPerformAssertions();
|
||||
$exportToon->exportDBCreate('testDB');
|
||||
}
|
||||
|
||||
public function testExportData(): void
|
||||
{
|
||||
$exportToon = $this->getExportToon();
|
||||
|
||||
$request = ServerRequestFactory::create()->createServerRequest('POST', 'https://example.com/')
|
||||
->withParsedBody([]);
|
||||
|
||||
$exportToon->setExportOptions($request, new Export());
|
||||
|
||||
ob_start();
|
||||
$exportToon->exportData('test_db', 'test_table', 'SELECT * FROM `test_db`.`test_table`;');
|
||||
$result = ob_get_clean();
|
||||
|
||||
self::assertIsString($result);
|
||||
self::assertSame(
|
||||
'test_db.test_table[3]{id,name,datetimefield}:' . "\n" .
|
||||
' 1,abcd,2011-01-20 02:00:02' . "\n" .
|
||||
' 2,foo,2010-01-20 02:00:02' . "\n" .
|
||||
' 3,Abcd,2012-01-20 02:00:02' . "\n\n",
|
||||
$result,
|
||||
);
|
||||
}
|
||||
|
||||
public function testExportDataWithCustomConfig(): void
|
||||
{
|
||||
$exportToon = $this->getExportToon();
|
||||
$request = ServerRequestFactory::create()->createServerRequest('POST', 'https://example.com/')
|
||||
->withParsedBody(['toon_separator' => '|', 'toon_indent' => '4']);
|
||||
|
||||
$exportToon->setExportOptions($request, new Export());
|
||||
|
||||
ob_start();
|
||||
$exportToon->exportData('test_db', 'test_table', 'SELECT * FROM `test_db`.`test_table`;');
|
||||
$result = ob_get_clean();
|
||||
|
||||
self::assertIsString($result);
|
||||
self::assertSame(
|
||||
'test_db.test_table[3|]{id|name|datetimefield}:' . "\n" .
|
||||
' 1|abcd|2011-01-20 02:00:02' . "\n" .
|
||||
' 2|foo|2010-01-20 02:00:02' . "\n" .
|
||||
' 3|Abcd|2012-01-20 02:00:02' . "\n\n",
|
||||
$result,
|
||||
);
|
||||
}
|
||||
|
||||
private function getExportToon(DatabaseInterface|null $dbi = null): ExportToon
|
||||
{
|
||||
$dbi ??= $this->createDatabaseInterface();
|
||||
$config = new Config();
|
||||
$relation = new Relation($dbi, $config);
|
||||
|
||||
return new ExportToon($relation, new OutputHandler(), new Transformations($dbi, $relation), $dbi, $config);
|
||||
}
|
||||
}
|
||||
@ -46,7 +46,7 @@ class PluginsTest extends AbstractTestCase
|
||||
$isCurl = extension_loaded('curl');
|
||||
self::assertSame(ExportType::Database, ExportPlugin::$exportType);
|
||||
self::assertFalse(ExportPlugin::$singleTable);
|
||||
$pluginCount = $isCurl ? 14 : 13;
|
||||
$pluginCount = $isCurl ? 15 : 14;
|
||||
self::assertCount($pluginCount, $plugins);
|
||||
self::assertContainsOnlyInstancesOf(ExportPlugin::class, $plugins);
|
||||
}
|
||||
@ -432,6 +432,12 @@ class PluginsTest extends AbstractTestCase
|
||||
<label for="text_texytext_null" class="form-label">Replace NULL with:</label><input class="form-control" type="text" name="texytext_null" value="NULL" id="text_texytext_null"></ul></div></li>
|
||||
</div>
|
||||
|
||||
<div id="toon_options" class="format_specific_options"><h3>TOON</h3>
|
||||
<div id="toon_general_opts"><ul class="list-group"><li class="list-group-item">
|
||||
<label for="text_toon_separator" class="form-label">Columns separated with:</label><input class="form-control" type="text" name="toon_separator" value="," id="text_toon_separator"><li class="list-group-item">
|
||||
<label for="text_toon_indent" class="form-label">Indentation:</label><input class="form-control" type="text" name="toon_indent" value="2" id="text_toon_indent"><li class="list-group-item"><input type="hidden" name="toon_structure_or_data" value="structure_and_data"></li></ul></div>
|
||||
</div>
|
||||
|
||||
<div id="yaml_options" class="format_specific_options"><h3>YAML</h3>
|
||||
<div id="yaml_general_opts"><ul class="list-group"><li class="list-group-item"><input type="hidden" name="yaml_structure_or_data" value="data"></li></ul></div>
|
||||
<p class="card-text">This format has no options</p></div>
|
||||
|
||||
Loading…
Reference in New Issue
Block a user