Remove excel_* global variables

Signed-off-by: Maurício Meneghini Fauth <mauricio@mfauth.net>
This commit is contained in:
Maurício Meneghini Fauth 2025-01-03 14:55:05 -03:00
parent 0ca6b2d73a
commit 1c57a44202
No known key found for this signature in database
GPG Key ID: 6A16FD38AFC89CC8
6 changed files with 108 additions and 266 deletions

View File

@ -11539,35 +11539,11 @@ parameters:
path: src/Plugins/Export/ExportCsv.php
-
message: '#^Binary operation "\." between mixed and \(list\<string\>\|string\) results in an error\.$#'
message: '#^Binary operation "\." between non\-empty\-string and \(list\<string\>\|string\) results in an error\.$#'
identifier: binaryOp.invalid
count: 1
path: src/Plugins/Export/ExportExcel.php
-
message: '#^Binary operation "\." between mixed and mixed results in an error\.$#'
identifier: binaryOp.invalid
count: 4
path: src/Plugins/Export/ExportExcel.php
-
message: '#^Binary operation "\." between mixed and string results in an error\.$#'
identifier: binaryOp.invalid
count: 2
path: src/Plugins/Export/ExportExcel.php
-
message: '#^Binary operation "\." between non\-empty\-string and mixed results in an error\.$#'
identifier: binaryOp.invalid
count: 3
path: src/Plugins/Export/ExportExcel.php
-
message: '#^Binary operation "\." between string and mixed results in an error\.$#'
identifier: binaryOp.invalid
count: 2
path: src/Plugins/Export/ExportExcel.php
-
message: '''
#^Call to deprecated method getInstance\(\) of class PhpMyAdmin\\Dbal\\DatabaseInterface\:
@ -11601,36 +11577,6 @@ parameters:
count: 1
path: src/Plugins/Export/ExportExcel.php
-
message: '#^Loose comparison via "\!\=" is not allowed\.$#'
identifier: notEqual.notAllowed
count: 1
path: src/Plugins/Export/ExportExcel.php
-
message: '#^Loose comparison via "\=\=" is not allowed\.$#'
identifier: equal.notAllowed
count: 2
path: src/Plugins/Export/ExportExcel.php
-
message: '#^Only booleans are allowed in &&, mixed given on the right side\.$#'
identifier: booleanAnd.rightNotBoolean
count: 3
path: src/Plugins/Export/ExportExcel.php
-
message: '#^Parameter \#1 \$search of function str_replace expects array\<string\>\|string, mixed given\.$#'
identifier: argument.type
count: 4
path: src/Plugins/Export/ExportExcel.php
-
message: '#^Parameter \#1 \$separator of function implode expects array\|string, mixed given\.$#'
identifier: argument.type
count: 2
path: src/Plugins/Export/ExportExcel.php
-
message: '#^Parameter \#3 \$subject of function str_replace expects array\<string\>\|string, mixed given\.$#'
identifier: argument.type

View File

@ -1427,10 +1427,6 @@
<code><![CDATA[$GLOBALS['csv_removeCRLF']]]></code>
<code><![CDATA[$GLOBALS['csv_separator']]]></code>
<code><![CDATA[$GLOBALS['csv_terminated']]]></code>
<code><![CDATA[$GLOBALS['excel_columns']]]></code>
<code><![CDATA[$GLOBALS['excel_edition']]]></code>
<code><![CDATA[$GLOBALS['excel_null']]]></code>
<code><![CDATA[$GLOBALS['excel_removeCRLF']]]></code>
<code><![CDATA[$GLOBALS['knjenc']]]></code>
<code><![CDATA[$GLOBALS['maxsize']]]></code>
<code><![CDATA[$GLOBALS['save_filename']]]></code>
@ -6787,67 +6783,16 @@
<code><![CDATA[DatabaseInterface::getInstance()]]></code>
<code><![CDATA[DatabaseInterface::getInstance()]]></code>
</DeprecatedMethod>
<InvalidArrayOffset>
<code><![CDATA[$GLOBALS['excel_columns']]]></code>
<code><![CDATA[$GLOBALS['excel_columns']]]></code>
<code><![CDATA[$GLOBALS['excel_enclosed']]]></code>
<code><![CDATA[$GLOBALS['excel_enclosed']]]></code>
<code><![CDATA[$GLOBALS['excel_escaped']]]></code>
<code><![CDATA[$GLOBALS['excel_escaped']]]></code>
<code><![CDATA[$GLOBALS['excel_null']]]></code>
<code><![CDATA[$GLOBALS['excel_separator']]]></code>
<code><![CDATA[$GLOBALS['excel_separator']]]></code>
<code><![CDATA[$GLOBALS['excel_terminated']]]></code>
</InvalidArrayOffset>
<MixedArgument>
<code><![CDATA[$GLOBALS['excel_enclosed']]]></code>
<code><![CDATA[$GLOBALS['excel_enclosed']]]></code>
<code><![CDATA[$GLOBALS['excel_enclosed']]]></code>
<code><![CDATA[$GLOBALS['excel_escaped']]]></code>
<code><![CDATA[$GLOBALS['excel_separator']]]></code>
<code><![CDATA[$GLOBALS['excel_separator']]]></code>
<code><![CDATA[$colAs]]></code>
</MixedArgument>
<MixedArgumentTypeCoercion>
<code><![CDATA[$insertFields]]></code>
<code><![CDATA[$insertValues]]></code>
</MixedArgumentTypeCoercion>
<MixedAssignment>
<code><![CDATA[$GLOBALS['excel_enclosed']]]></code>
<code><![CDATA[$GLOBALS['excel_enclosed']]]></code>
<code><![CDATA[$GLOBALS['excel_escaped']]]></code>
<code><![CDATA[$GLOBALS['excel_escaped']]]></code>
<code><![CDATA[$GLOBALS['excel_separator']]]></code>
<code><![CDATA[$GLOBALS['excel_separator']]]></code>
<code><![CDATA[$GLOBALS['excel_terminated']]]></code>
<code><![CDATA[$colAs]]></code>
<code><![CDATA[$insertFields[]]]></code>
<code><![CDATA[$insertValues[]]]></code>
</MixedAssignment>
<MixedOperand>
<code><![CDATA[$GLOBALS['excel_enclosed']]]></code>
<code><![CDATA[$GLOBALS['excel_enclosed']]]></code>
<code><![CDATA[$GLOBALS['excel_enclosed']]]></code>
<code><![CDATA[$GLOBALS['excel_enclosed']]]></code>
<code><![CDATA[$GLOBALS['excel_enclosed']]]></code>
<code><![CDATA[$GLOBALS['excel_enclosed']]]></code>
<code><![CDATA[$GLOBALS['excel_escaped']]]></code>
<code><![CDATA[$GLOBALS['excel_escaped']]]></code>
<code><![CDATA[$GLOBALS['excel_escaped']]]></code>
<code><![CDATA[$GLOBALS['excel_escaped']]]></code>
<code><![CDATA[$GLOBALS['excel_terminated']]]></code>
<code><![CDATA[$GLOBALS['excel_terminated']]]></code>
</MixedOperand>
<PossiblyNullArgument>
<code><![CDATA[$GLOBALS['excel_enclosed']]]></code>
<code><![CDATA[$GLOBALS['excel_enclosed']]]></code>
<code><![CDATA[$GLOBALS['excel_enclosed']]]></code>
<code><![CDATA[$GLOBALS['excel_escaped']]]></code>
</PossiblyNullArgument>
<RedundantCondition>
<code><![CDATA[$GLOBALS['excel_removeCRLF']]]></code>
<code><![CDATA[isset($GLOBALS['excel_removeCRLF']) && $GLOBALS['excel_removeCRLF']]]></code>
</RedundantCondition>
</file>
<file src="src/Plugins/Export/ExportHtmlword.php">
<DeprecatedMethod>
@ -12840,32 +12785,6 @@
<code><![CDATA[providerForTestValidPlugins]]></code>
</PossiblyUnusedMethod>
</file>
<file src="tests/unit/Plugins/Export/ExportExcelTest.php">
<DocblockTypeContradiction>
<code><![CDATA[assertSame]]></code>
</DocblockTypeContradiction>
<InvalidArrayOffset>
<code><![CDATA[$GLOBALS['excel_enclosed']]]></code>
<code><![CDATA[$GLOBALS['excel_escaped']]]></code>
<code><![CDATA[$GLOBALS['excel_separator']]]></code>
<code><![CDATA[$GLOBALS['excel_terminated']]]></code>
</InvalidArrayOffset>
<RedundantCondition>
<code><![CDATA[assertFalse]]></code>
<code><![CDATA[assertSame]]></code>
<code><![CDATA[assertTrue]]></code>
</RedundantCondition>
<RedundantConditionGivenDocblockType>
<code><![CDATA[assertFalse]]></code>
<code><![CDATA[assertSame]]></code>
<code><![CDATA[assertSame]]></code>
<code><![CDATA[assertSame]]></code>
<code><![CDATA[assertSame]]></code>
<code><![CDATA[assertSame]]></code>
<code><![CDATA[assertSame]]></code>
<code><![CDATA[assertSame]]></code>
</RedundantConditionGivenDocblockType>
</file>
<file src="tests/unit/Plugins/Export/ExportHtmlwordTest.php">
<DeprecatedMethod>
<code><![CDATA[Config::getInstance()]]></code>

View File

@ -54,7 +54,6 @@
display_query: string,
errno: int,
error: bool,
excel_edition: 'win'|'mac_excel2003'|'mac_excel2008',
file_handle: resource|null,
from_cookie: bool,
hostname: string,

View File

@ -493,22 +493,6 @@ final class ExportController implements InvocableController
$GLOBALS['xkana'] = $postParams['xkana'];
}
if (isset($postParams['excel_null'])) {
$GLOBALS['excel_null'] = $postParams['excel_null'];
}
if (isset($postParams['excel_removeCRLF'])) {
$GLOBALS['excel_removeCRLF'] = $postParams['excel_removeCRLF'];
}
if (isset($postParams['excel_columns'])) {
$GLOBALS['excel_columns'] = $postParams['excel_columns'];
}
if (isset($postParams['excel_edition'])) {
$GLOBALS['excel_edition'] = $postParams['excel_edition'];
}
if (isset($postParams['csv_separator'])) {
$GLOBALS['csv_separator'] = $postParams['csv_separator'];
}

View File

@ -22,6 +22,8 @@ use PhpMyAdmin\Properties\Plugins\ExportPluginProperties;
use function __;
use function implode;
use function in_array;
use function is_string;
use function preg_replace;
use function str_replace;
@ -30,6 +32,16 @@ use function str_replace;
*/
class ExportExcel extends ExportPlugin
{
/** @var 'win'|'mac_excel2003'|'mac_excel2008' */
private string $edition = 'win';
private bool $columns = false;
private bool $removeCrLf = false;
private string $null = 'NULL';
private string $separator = ',';
private string $enclosed = '"';
private string $escaped = '"';
private string $terminated = '';
/** @psalm-return non-empty-lowercase-string */
public function getName(): string
{
@ -95,25 +107,20 @@ class ExportExcel extends ExportPlugin
*/
public function exportHeader(): bool
{
$GLOBALS['excel_separator'] ??= null;
$GLOBALS['excel_enclosed'] ??= null;
$GLOBALS['excel_escaped'] ??= null;
// Here we just prepare some values for export
$GLOBALS['excel_terminated'] = "\015\012";
switch ($GLOBALS['excel_edition']) {
$this->terminated = "\015\012";
switch ($this->edition) {
case 'win': // as tested on Windows with Excel 2002 and Excel 2007
case 'mac_excel2003':
$GLOBALS['excel_separator'] = ';';
$this->separator = ';';
break;
case 'mac_excel2008':
$GLOBALS['excel_separator'] = ',';
$this->separator = ',';
break;
}
$GLOBALS['excel_enclosed'] = '"';
$GLOBALS['excel_escaped'] = '"';
$GLOBALS['excel_columns'] = isset($GLOBALS['excel_columns']) && $GLOBALS['excel_columns'];
$this->enclosed = '"';
$this->escaped = '"';
return true;
}
@ -172,11 +179,6 @@ class ExportExcel extends ExportPlugin
string $sqlQuery,
array $aliases = [],
): bool {
$GLOBALS['excel_terminated'] ??= null;
$GLOBALS['excel_separator'] ??= '';
$GLOBALS['excel_enclosed'] ??= null;
$GLOBALS['excel_escaped'] ??= null;
$dbAlias = $db;
$tableAlias = $table;
$this->initAlias($aliases, $dbAlias, $tableAlias);
@ -188,28 +190,24 @@ class ExportExcel extends ExportPlugin
$result = $dbi->query($sqlQuery, ConnectionType::User, DatabaseInterface::QUERY_UNBUFFERED);
// If required, get fields name at the first line
if (isset($GLOBALS['excel_columns']) && $GLOBALS['excel_columns']) {
if ($this->columns) {
$insertFields = [];
foreach ($result->getFieldNames() as $colAs) {
if (! empty($aliases[$db]['tables'][$table]['columns'][$colAs])) {
$colAs = $aliases[$db]['tables'][$table]['columns'][$colAs];
}
if ($GLOBALS['excel_enclosed'] == '') {
if ($this->enclosed === '') {
$insertFields[] = $colAs;
} else {
$insertFields[] = $GLOBALS['excel_enclosed']
. str_replace(
$GLOBALS['excel_enclosed'],
$GLOBALS['excel_escaped'] . $GLOBALS['excel_enclosed'],
$colAs,
)
. $GLOBALS['excel_enclosed'];
$insertFields[] = $this->enclosed
. str_replace($this->enclosed, $this->escaped . $this->enclosed, $colAs)
. $this->enclosed;
}
}
$schemaInsert = implode($GLOBALS['excel_separator'], $insertFields);
if (! $this->export->outputHandler($schemaInsert . $GLOBALS['excel_terminated'])) {
$schemaInsert = implode($this->separator, $insertFields);
if (! $this->export->outputHandler($schemaInsert . $this->terminated)) {
return false;
}
}
@ -219,13 +217,13 @@ class ExportExcel extends ExportPlugin
$insertValues = [];
foreach ($row as $field) {
if ($field === null) {
$insertValues[] = $GLOBALS['excel_null'];
$insertValues[] = $this->null;
} elseif ($field !== '') {
// always enclose fields
$field = preg_replace("/\015(\012)?/", "\012", $field);
// remove CRLF characters within field
if (isset($GLOBALS['excel_removeCRLF']) && $GLOBALS['excel_removeCRLF']) {
if ($this->removeCrLf) {
$field = str_replace(
["\r", "\n"],
'',
@ -233,38 +231,34 @@ class ExportExcel extends ExportPlugin
);
}
if ($GLOBALS['excel_enclosed'] == '') {
if ($this->enclosed === '') {
$insertValues[] = $field;
} elseif ($GLOBALS['excel_escaped'] != $GLOBALS['excel_enclosed']) {
} elseif ($this->escaped !== $this->enclosed) {
// also double the escape string if found in the data
$insertValues[] = $GLOBALS['excel_enclosed']
$insertValues[] = $this->enclosed
. str_replace(
$GLOBALS['excel_enclosed'],
$GLOBALS['excel_escaped'] . $GLOBALS['excel_enclosed'],
$this->enclosed,
$this->escaped . $this->enclosed,
str_replace(
$GLOBALS['excel_escaped'],
$GLOBALS['excel_escaped'] . $GLOBALS['excel_escaped'],
$this->escaped,
$this->escaped . $this->escaped,
$field,
),
)
. $GLOBALS['excel_enclosed'];
. $this->enclosed;
} else {
// avoid a problem when escape string equals enclose
$insertValues[] = $GLOBALS['excel_enclosed']
. str_replace(
$GLOBALS['excel_enclosed'],
$GLOBALS['excel_escaped'] . $GLOBALS['excel_enclosed'],
$field,
)
. $GLOBALS['excel_enclosed'];
$insertValues[] = $this->enclosed
. str_replace($this->enclosed, $this->escaped . $this->enclosed, $field)
. $this->enclosed;
}
} else {
$insertValues[] = '';
}
}
$schemaInsert = implode($GLOBALS['excel_separator'], $insertValues);
if (! $this->export->outputHandler($schemaInsert . $GLOBALS['excel_terminated'])) {
$schemaInsert = implode($this->separator, $insertValues);
if (! $this->export->outputHandler($schemaInsert . $this->terminated)) {
return false;
}
}
@ -295,5 +289,56 @@ class ExportExcel extends ExportPlugin
$exportConfig['excel_structure_or_data'] ?? null,
StructureOrData::Data,
);
$this->edition = $this->setEdition($this->setStringValue(
$request->getParsedBodyParam('excel_edition'),
$exportConfig['excel_edition'] ?? null,
));
$this->columns = (bool) ($request->getParsedBodyParam('excel_columns')
?? $exportConfig['excel_columns'] ?? false);
$this->removeCrLf = (bool) ($request->getParsedBodyParam('excel_removeCRLF')
?? $exportConfig['excel_removeCRLF'] ?? false);
$this->null = $this->setStringValue(
$request->getParsedBodyParam('excel_null'),
$exportConfig['excel_null'] ?? null,
);
$this->separator = $this->setStringValue(
$request->getParsedBodyParam('excel_separator'),
$exportConfig['excel_separator'] ?? null,
);
$this->enclosed = $this->setStringValue(
$request->getParsedBodyParam('excel_enclosed'),
$exportConfig['excel_enclosed'] ?? null,
);
$this->escaped = $this->setStringValue(
$request->getParsedBodyParam('excel_escaped'),
$exportConfig['excel_escaped'] ?? null,
);
$this->terminated = $this->setStringValue(
$request->getParsedBodyParam('excel_terminated'),
$exportConfig['excel_terminated'] ?? null,
);
}
private function setStringValue(mixed $fromRequest, mixed $fromConfig): string
{
if (is_string($fromRequest) && $fromRequest !== '') {
return $fromRequest;
}
if (is_string($fromConfig) && $fromConfig !== '') {
return $fromConfig;
}
return '';
}
/** @return 'win'|'mac_excel2003'|'mac_excel2008' */
private function setEdition(string $edition): string
{
if (in_array($edition, ['mac_excel2003', 'mac_excel2008'], true)) {
return $edition;
}
return 'win';
}
}

View File

@ -7,6 +7,7 @@ namespace PhpMyAdmin\Tests\Plugins\Export;
use PhpMyAdmin\ConfigStorage\Relation;
use PhpMyAdmin\Dbal\DatabaseInterface;
use PhpMyAdmin\Export\Export;
use PhpMyAdmin\Http\Factory\ServerRequestFactory;
use PhpMyAdmin\Plugins\Export\ExportExcel;
use PhpMyAdmin\Properties\Options\Groups\OptionsPropertyMainGroup;
use PhpMyAdmin\Properties\Options\Groups\OptionsPropertyRootGroup;
@ -190,79 +191,34 @@ class ExportExcelTest extends AbstractTestCase
public function testExportHeader(): void
{
// case 1
$GLOBALS['excel_edition'] = 'win';
$GLOBALS['excel_columns'] = true;
self::assertTrue(
$this->object->exportHeader(),
);
self::assertSame("\015\012", $GLOBALS['excel_terminated']);
self::assertSame(';', $GLOBALS['excel_separator']);
self::assertSame('"', $GLOBALS['excel_enclosed']);
self::assertSame('"', $GLOBALS['excel_escaped']);
self::assertTrue($GLOBALS['excel_columns']);
// case 2
$request = ServerRequestFactory::create()->createServerRequest('POST', 'https://example.com/')
->withParsedBody(['excel_edition' => 'mac_excel2003']);
$GLOBALS['excel_edition'] = 'mac_excel2003';
unset($GLOBALS['excel_columns']);
$GLOBALS['excel_columns'] = false;
$this->object->setExportOptions($request, []);
self::assertTrue(
$this->object->exportHeader(),
);
self::assertSame("\015\012", $GLOBALS['excel_terminated']);
self::assertSame(';', $GLOBALS['excel_separator']);
self::assertSame('"', $GLOBALS['excel_enclosed']);
self::assertSame('"', $GLOBALS['excel_escaped']);
self::assertFalse($GLOBALS['excel_columns']);
// case 3
$request = ServerRequestFactory::create()->createServerRequest('POST', 'https://example.com/')
->withParsedBody(['excel_edition' => 'mac_excel2008']);
$GLOBALS['excel_edition'] = 'mac_excel2008';
$this->object->setExportOptions($request, []);
self::assertTrue(
$this->object->exportHeader(),
);
self::assertSame("\015\012", $GLOBALS['excel_terminated']);
self::assertSame(',', $GLOBALS['excel_separator']);
self::assertSame('"', $GLOBALS['excel_enclosed']);
self::assertSame('"', $GLOBALS['excel_escaped']);
self::assertFalse($GLOBALS['excel_columns']);
// case 4
$GLOBALS['excel_edition'] = 'testBlank';
$GLOBALS['excel_separator'] = '#';
self::assertTrue(
$this->object->exportHeader(),
);
self::assertSame('#', $GLOBALS['excel_separator']);
}
public function testExportData(): void
{
// case 1
$GLOBALS['excel_columns'] = true;
$GLOBALS['excel_terminated'] = ';';
$GLOBALS['output_kanji_conversion'] = false;
$GLOBALS['output_charset_conversion'] = false;
$GLOBALS['buffer_needed'] = false;
@ -279,14 +235,16 @@ class ExportExcelTest extends AbstractTestCase
ob_get_clean();
// case 2
$GLOBALS['excel_null'] = 'customNull';
$GLOBALS['output_kanji_conversion'] = false;
$GLOBALS['output_charset_conversion'] = false;
$GLOBALS['buffer_needed'] = false;
$GLOBALS['asfile'] = true;
$GLOBALS['save_on_server'] = false;
$GLOBALS['excel_enclosed'] = '';
$GLOBALS['excel_separator'] = '';
$request = ServerRequestFactory::create()->createServerRequest('POST', 'https://example.com/')
->withParsedBody(['excel_columns' => 'On', 'excel_terminated' => ';']);
$this->object->setExportOptions($request, []);
ob_start();
self::assertTrue($this->object->exportData(
@ -302,8 +260,10 @@ class ExportExcelTest extends AbstractTestCase
);
// case 3
$GLOBALS['excel_enclosed'] = '"';
$GLOBALS['excel_escaped'] = '';
$request = ServerRequestFactory::create()->createServerRequest('POST', 'https://example.com/')
->withParsedBody(['excel_columns' => 'On', 'excel_enclosed' => '"', 'excel_terminated' => ';']);
$this->object->setExportOptions($request, []);
ob_start();
self::assertTrue($this->object->exportData(
@ -320,10 +280,6 @@ class ExportExcelTest extends AbstractTestCase
);
// case 4
$GLOBALS['excel_enclosed'] = '"';
$GLOBALS['excel_removeCRLF'] = true;
$GLOBALS['excel_escaped'] = '"';
ob_start();
self::assertTrue($this->object->exportData(
'test_db',
@ -339,10 +295,6 @@ class ExportExcelTest extends AbstractTestCase
);
// case 5
$GLOBALS['excel_enclosed'] = '"';
unset($GLOBALS['excel_removeCRLF']);
$GLOBALS['excel_escaped'] = ';';
ob_start();
self::assertTrue($this->object->exportData(
'test_db',
@ -358,9 +310,6 @@ class ExportExcelTest extends AbstractTestCase
);
// case 6
$GLOBALS['excel_enclosed'] = '"';
$GLOBALS['excel_escaped'] = '#';
ob_start();
self::assertTrue($this->object->exportData(
'test_db',