Skip to content

Commit c82ad3e

Browse files
committed
Fix export template update error
When updating an export template, the exportType request parameter is ignored by the controller, because it's not used by the UPDATE statement. However the Template value object requires a valid ExportType enum, causing a ValueError to be thrown. ``` ValueError: "" is not a valid backing value for enum PhpMyAdmin\Plugins\ExportType ``` Signed-off-by: Maurício Meneghini Fauth <mauricio@mfauth.net>
1 parent 99d1a9b commit c82ad3e

6 files changed

Lines changed: 109 additions & 9 deletions

File tree

phpstan-baseline.neon

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6412,7 +6412,7 @@ parameters:
64126412
path: src/Export/Template.php
64136413

64146414
-
6415-
message: '#^Parameter \#1 \$value of static method PhpMyAdmin\\Plugins\\ExportType\:\:from\(\) expects int\|string, mixed given\.$#'
6415+
message: '#^Parameter \#1 \$value of static method PhpMyAdmin\\Plugins\\ExportType\:\:tryFrom\(\) expects int\|string, mixed given\.$#'
64166416
identifier: argument.type
64176417
count: 1
64186418
path: src/Export/Template.php

psalm-baseline.xml

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1365,11 +1365,6 @@
13651365
<code><![CDATA[Response]]></code>
13661366
</PossiblyUnusedReturnValue>
13671367
</file>
1368-
<file src="src/Controllers/Export/Template/UpdateController.php">
1369-
<PossiblyUnusedReturnValue>
1370-
<code><![CDATA[Response]]></code>
1371-
</PossiblyUnusedReturnValue>
1372-
</file>
13731368
<file src="src/Controllers/GitInfoController.php">
13741369
<PossiblyUnusedMethod>
13751370
<code><![CDATA[__construct]]></code>

src/Controllers/Export/Template/UpdateController.php

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ public function __invoke(ServerRequest $request): Response
2929
{
3030
$templateId = (int) $request->getParsedBodyParamAsStringOrNull('templateId');
3131
$templateData = $request->getParsedBodyParamAsString('templateData', '');
32+
$exportType = $request->getParsedBodyParamAsString('exportType', '');
3233

3334
$exportTemplatesFeature = $this->relation->getRelationParameters()->exportTemplatesFeature;
3435
if ($exportTemplatesFeature === null) {
@@ -37,6 +38,7 @@ public function __invoke(ServerRequest $request): Response
3738

3839
$template = ExportTemplate::fromArray([
3940
'id' => $templateId,
41+
'exportType' => $exportType,
4042
'username' => $this->config->selectedServer['user'],
4143
'data' => $templateData,
4244
]);

src/Export/Template.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ public static function fromArray(array $state): self
2424
return new self(
2525
$state['id'] ?? 0,
2626
$state['username'],
27-
ExportType::from($state['exportType'] ?? ''),
27+
ExportType::tryFrom($state['exportType'] ?? '') ?? ExportType::Server,
2828
$state['name'] ?? '',
2929
$state['data'],
3030
);

tests/unit/Controllers/Export/Template/UpdateControllerTest.php

Lines changed: 47 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,19 +4,23 @@
44

55
namespace PhpMyAdmin\Tests\Controllers\Export\Template;
66

7+
use Fig\Http\Message\StatusCodeInterface;
78
use PhpMyAdmin\Config;
89
use PhpMyAdmin\ConfigStorage\Relation;
10+
use PhpMyAdmin\ConfigStorage\RelationParameters;
911
use PhpMyAdmin\Controllers\Export\Template\UpdateController;
1012
use PhpMyAdmin\Dbal\DatabaseInterface;
1113
use PhpMyAdmin\Export\TemplateModel;
14+
use PhpMyAdmin\Http\Factory\ServerRequestFactory;
1215
use PhpMyAdmin\Http\ServerRequest;
1316
use PhpMyAdmin\Tests\AbstractTestCase;
1417
use PhpMyAdmin\Tests\Stubs\DbiDummy;
1518
use PhpMyAdmin\Tests\Stubs\ResponseRenderer;
1619
use PHPUnit\Framework\Attributes\CoversClass;
20+
use ReflectionProperty;
1721

1822
#[CoversClass(UpdateController::class)]
19-
class UpdateControllerTest extends AbstractTestCase
23+
final class UpdateControllerTest extends AbstractTestCase
2024
{
2125
protected DatabaseInterface $dbi;
2226

@@ -31,8 +35,10 @@ protected function setUp(): void
3135
DatabaseInterface::$instance = $this->dbi;
3236
}
3337

34-
public function testUpdate(): void
38+
public function testWithoutTemplatesFeature(): void
3539
{
40+
(new ReflectionProperty(Relation::class, 'cache'))->setValue(null, RelationParameters::fromArray([]));
41+
3642
$config = Config::getInstance();
3743
$config->selectedServer['user'] = 'user';
3844

@@ -48,4 +54,43 @@ public function testUpdate(): void
4854

4955
self::assertTrue($response->hasSuccessState());
5056
}
57+
58+
public function testWithTemplatesFeature(): void
59+
{
60+
$relationParameters = RelationParameters::fromArray([
61+
RelationParameters::USER => 'test_user',
62+
RelationParameters::DATABASE => 'pma_db',
63+
RelationParameters::EXPORT_TEMPLATES_WORK => true,
64+
RelationParameters::EXPORT_TEMPLATES => 'export_templates',
65+
]);
66+
(new ReflectionProperty(Relation::class, 'cache'))->setValue(null, $relationParameters);
67+
68+
$config = new Config();
69+
$config->selectedServer['user'] = 'test_user';
70+
71+
$dbiDummy = $this->createDbiDummy();
72+
$dbiDummy->removeDefaultResults();
73+
74+
// phpcs:disable Generic.Files.LineLength.TooLong
75+
$dbiDummy->addResult('UPDATE `pma_db`.`export_templates` SET `template_data` = \'{\"quick_or_custom\":\"quick\"}\' WHERE `id` = 1 AND `username` = \'test_user\';', true);
76+
$dbi = $this->createDatabaseInterface($dbiDummy);
77+
78+
$responseRenderer = new ResponseRenderer();
79+
$request = ServerRequestFactory::create()->createServerRequest('POST', 'https://example.com/')->withParsedBody([
80+
'exportType' => 'server',
81+
'templateId' => '1',
82+
'templateData' => '{"quick_or_custom":"quick"}',
83+
]);
84+
85+
$response = (new UpdateController(
86+
$responseRenderer,
87+
new TemplateModel($dbi),
88+
new Relation($dbi, $config),
89+
$config,
90+
))($request);
91+
92+
$dbiDummy->assertAllQueriesConsumed();
93+
self::assertTrue($responseRenderer->hasSuccessState());
94+
self::assertSame(StatusCodeInterface::STATUS_OK, $response->getStatusCode());
95+
}
5196
}

tests/unit/Export/TemplateTest.php

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace PhpMyAdmin\Tests\Export;
6+
7+
use PhpMyAdmin\Export\Template;
8+
use PhpMyAdmin\Plugins\ExportType;
9+
use PHPUnit\Framework\Attributes\CoversClass;
10+
use PHPUnit\Framework\Attributes\DataProvider;
11+
use PHPUnit\Framework\TestCase;
12+
13+
#[CoversClass(Template::class)]
14+
final class TemplateTest extends TestCase
15+
{
16+
/** @param array<string, int|string> $state */
17+
#[DataProvider('fromArrayProvider')]
18+
public function testFromArray(
19+
int $id,
20+
string $username,
21+
ExportType $exportType,
22+
string $name,
23+
string $data,
24+
array $state,
25+
): void {
26+
$template = Template::fromArray($state);
27+
self::assertSame($id, $template->getId());
28+
self::assertSame($username, $template->getUsername());
29+
self::assertSame($exportType, $template->getExportType());
30+
self::assertSame($name, $template->getName());
31+
self::assertSame($data, $template->getData());
32+
}
33+
34+
/** @return iterable<int, array{int, string, ExportType, string, string, array<string, int|string>}> */
35+
public static function fromArrayProvider(): iterable
36+
{
37+
yield [0, '', ExportType::Server, '', '', ['username' => '', 'data' => '']];
38+
yield [0, '', ExportType::Server, '', '', ['username' => '', 'data' => '', 'exportType' => 'server']];
39+
yield [0, '', ExportType::Server, '', '', ['username' => '', 'data' => '', 'exportType' => 'invalid']];
40+
yield [0, '', ExportType::Database, '', '', ['username' => '', 'data' => '', 'exportType' => 'database']];
41+
yield [0, '', ExportType::Table, '', '', ['username' => '', 'data' => '', 'exportType' => 'table']];
42+
yield [0, '', ExportType::Raw, '', '', ['username' => '', 'data' => '', 'exportType' => 'raw']];
43+
yield [
44+
1,
45+
'test_user',
46+
ExportType::Database,
47+
'Template name',
48+
'{"template":"data"}',
49+
[
50+
'id' => 1,
51+
'username' => 'test_user',
52+
'exportType' => 'database',
53+
'name' => 'Template name',
54+
'data' => '{"template":"data"}',
55+
],
56+
];
57+
}
58+
}

0 commit comments

Comments
 (0)