Merge branch 'QA_5_2'
Signed-off-by: William Desportes <williamdes@wdes.fr>
This commit is contained in:
commit
015d75c0d1
42
.github/workflows/test-selenium.yml
vendored
42
.github/workflows/test-selenium.yml
vendored
@ -13,11 +13,28 @@ permissions:
|
||||
|
||||
env:
|
||||
php-version: "8.2"
|
||||
node-version: "20"
|
||||
|
||||
jobs:
|
||||
generate-matrix:
|
||||
name: Generate the matrix of Selenium tests
|
||||
if: "!contains(github.event.head_commit.message, '[ci selenium skip]')"
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
tests: ${{ steps.tests-list.outputs.tests }}
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6
|
||||
- id: tests-list
|
||||
name: Send test names to outputs
|
||||
run: |
|
||||
set -euo pipefail
|
||||
TEST_NAMES="[$(find $PWD/tests/end-to-end/ -type f -name '*Test.php' -print |sed -E "s,$PWD/tests/end-to-end/(.*)Test.php,{\"test-name\": \"\1\"}," | paste -sd ",")]"
|
||||
echo "tests=$(printf "$TEST_NAMES")" >> $GITHUB_OUTPUT
|
||||
selenium:
|
||||
name: "Selenium"
|
||||
if: "!contains(github.event.head_commit.message, '[ci selenium skip]')"
|
||||
needs: generate-matrix
|
||||
runs-on: "ubuntu-latest"
|
||||
services:
|
||||
database-server:
|
||||
@ -58,28 +75,7 @@ jobs:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
test-name:
|
||||
- "ChangePassword"
|
||||
- "CreateDropDatabase"
|
||||
- "CreateRemoveUser"
|
||||
- "Database/Events"
|
||||
- "Database/Operations"
|
||||
- "Database/Procedures"
|
||||
- "Database/Structure"
|
||||
- "Export"
|
||||
- "Import"
|
||||
- "Login"
|
||||
- "Normalization"
|
||||
- "ServerSettings"
|
||||
- "SqlQuery"
|
||||
- "Table/Browse"
|
||||
- "Table/Create"
|
||||
- "Table/Insert"
|
||||
- "Table/Operations"
|
||||
- "Table/Structure"
|
||||
- "Tracking"
|
||||
- "Triggers"
|
||||
- "Xss"
|
||||
include: ${{ fromJSON(needs.generate-matrix.outputs.tests) }}
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v6
|
||||
@ -103,7 +99,7 @@ jobs:
|
||||
- name: Set up Node
|
||||
uses: actions/setup-node@v6
|
||||
with:
|
||||
node-version: '20'
|
||||
node-version: '${{ env.node-version }}'
|
||||
cache: 'yarn'
|
||||
|
||||
- name: Install modules
|
||||
|
||||
@ -7092,7 +7092,7 @@ parameters:
|
||||
-
|
||||
message: '#^Cannot cast mixed to string\.$#'
|
||||
identifier: cast.string
|
||||
count: 6
|
||||
count: 7
|
||||
path: src/Import/Import.php
|
||||
|
||||
-
|
||||
@ -7125,6 +7125,12 @@ parameters:
|
||||
count: 1
|
||||
path: src/Import/Import.php
|
||||
|
||||
-
|
||||
message: '#^Only booleans are allowed in a negated boolean, int\|false given\.$#'
|
||||
identifier: booleanNot.exprNotBoolean
|
||||
count: 1
|
||||
path: src/Import/Import.php
|
||||
|
||||
-
|
||||
message: '#^Parameter \#1 \$precision of static method PhpMyAdmin\\Import\\DecimalSize\:\:fromPrecisionAndScale\(\) expects int, int\|PhpMyAdmin\\Import\\DecimalSize given\.$#'
|
||||
identifier: argument.type
|
||||
@ -8634,24 +8640,6 @@ parameters:
|
||||
count: 1
|
||||
path: src/Plugins/Export/ExportJson.php
|
||||
|
||||
-
|
||||
message: '#^Cannot call method fetchAssoc\(\) on PhpMyAdmin\\Dbal\\ResultInterface\|false\.$#'
|
||||
identifier: method.nonObject
|
||||
count: 1
|
||||
path: src/Plugins/Export/ExportLatex.php
|
||||
|
||||
-
|
||||
message: '#^Cannot call method getFieldNames\(\) on PhpMyAdmin\\Dbal\\ResultInterface\|false\.$#'
|
||||
identifier: method.nonObject
|
||||
count: 1
|
||||
path: src/Plugins/Export/ExportLatex.php
|
||||
|
||||
-
|
||||
message: '#^Cannot call method numFields\(\) on PhpMyAdmin\\Dbal\\ResultInterface\|false\.$#'
|
||||
identifier: method.nonObject
|
||||
count: 1
|
||||
path: src/Plugins/Export/ExportLatex.php
|
||||
|
||||
-
|
||||
message: '#^Construct empty\(\) is not allowed\. Use more strict comparison\.$#'
|
||||
identifier: empty.notAllowed
|
||||
|
||||
@ -1316,6 +1316,7 @@
|
||||
</RiskyTruthyFalsyComparison>
|
||||
<UnusedVariable>
|
||||
<code><![CDATA[$collationsList]]></code>
|
||||
<code><![CDATA[$encryptionKeyLength]]></code>
|
||||
</UnusedVariable>
|
||||
</file>
|
||||
<file src="src/Controllers/Import/ImportController.php">
|
||||
@ -4048,9 +4049,6 @@
|
||||
<code><![CDATA[$_POST['url']]]></code>
|
||||
<code><![CDATA[$exception['url']]]></code>
|
||||
</PossiblyInvalidCast>
|
||||
<PossiblyUndefinedArrayOffset>
|
||||
<code><![CDATA[$_SERVER['HTTP_USER_AGENT']]]></code>
|
||||
</PossiblyUndefinedArrayOffset>
|
||||
<RiskyTruthyFalsyComparison>
|
||||
<code><![CDATA[empty($_POST['description'])]]></code>
|
||||
<code><![CDATA[empty($_POST['exception'])]]></code>
|
||||
@ -4973,6 +4971,9 @@
|
||||
<code><![CDATA[$lastCumulativeSize->scale]]></code>
|
||||
<code><![CDATA[$lastCumulativeSize->scale]]></code>
|
||||
</PossiblyInvalidPropertyFetch>
|
||||
<PossiblyUndefinedArrayOffset>
|
||||
<code><![CDATA[$row[$columnIndex]]]></code>
|
||||
</PossiblyUndefinedArrayOffset>
|
||||
<RiskyTruthyFalsyComparison>
|
||||
<code><![CDATA[ImportSettings::$runQuery]]></code>
|
||||
</RiskyTruthyFalsyComparison>
|
||||
@ -5820,16 +5821,12 @@
|
||||
<MixedOperand>
|
||||
<code><![CDATA[$comments[$fieldName]]]></code>
|
||||
</MixedOperand>
|
||||
<PossiblyFalseReference>
|
||||
<code><![CDATA[fetchAssoc]]></code>
|
||||
<code><![CDATA[getFieldNames]]></code>
|
||||
<code><![CDATA[numFields]]></code>
|
||||
</PossiblyFalseReference>
|
||||
<PossiblyInvalidOperand>
|
||||
<code><![CDATA[str_replace('_', '/', $mimeMap[$fieldName]['mimetype'])]]></code>
|
||||
</PossiblyInvalidOperand>
|
||||
<PossiblyNullArgument>
|
||||
<code><![CDATA[$record[$columns[$i]]]]></code>
|
||||
<code><![CDATA[$record[$columns[$i]]]]></code>
|
||||
</PossiblyNullArgument>
|
||||
<RiskyTruthyFalsyComparison>
|
||||
<code><![CDATA[empty($this->config->selectedServer['port'])]]></code>
|
||||
@ -5882,6 +5879,11 @@
|
||||
<code><![CDATA[$pdf]]></code>
|
||||
</PropertyNotSetInConstructor>
|
||||
</file>
|
||||
<file src="src/Plugins/Export/ExportPhparray.php">
|
||||
<PossiblyNullArgument>
|
||||
<code><![CDATA[$record[$i]]]></code>
|
||||
</PossiblyNullArgument>
|
||||
</file>
|
||||
<file src="src/Plugins/Export/ExportSql.php">
|
||||
<ArgumentTypeCoercion>
|
||||
<code><![CDATA[$token->value]]></code>
|
||||
|
||||
@ -510,6 +510,26 @@ const rect = function (x1, y1, w, h, color) {
|
||||
};
|
||||
|
||||
// --------------------------- FULLSCREEN -------------------------------------
|
||||
const requestFullscreen = function (e) {
|
||||
if (e.requestFullscreen) {
|
||||
return e.requestFullscreen();
|
||||
} else if (e.webkitRequestFullscreen) {
|
||||
return e.webkitRequestFullscreen();
|
||||
} else if (e.mozRequestFullScreen) {
|
||||
return e.mozRequestFullScreen();
|
||||
} else if (e.msRequestFullscreen) {
|
||||
return e.msRequestFullscreen();
|
||||
}
|
||||
};
|
||||
|
||||
const fullscreenEnabled = function () {
|
||||
// eslint-disable-next-line compat/compat
|
||||
return document.fullscreenEnabled ||
|
||||
document.webkitFullscreenEnabled ||
|
||||
document.mozFullScreenEnabled ||
|
||||
document.msFullscreenEnabled;
|
||||
};
|
||||
|
||||
const toggleFullscreen = function () {
|
||||
var valueSent = '';
|
||||
var $img = $('#toggleFullscreen').find('img');
|
||||
@ -517,7 +537,7 @@ const toggleFullscreen = function () {
|
||||
var $content = $('#page_content');
|
||||
const pageContent = document.getElementById('page_content');
|
||||
|
||||
if (! document.fullscreenEnabled) {
|
||||
if (! DesignerMove.fullscreenEnabled()) {
|
||||
ajaxShowMessage(window.Messages.strFullscreenRequestDenied, null, 'error');
|
||||
|
||||
return;
|
||||
@ -534,7 +554,7 @@ const toggleFullscreen = function () {
|
||||
|
||||
$('#osn_tab').css({ 'width': screen.width + 'px', 'height': screen.height });
|
||||
valueSent = 'on';
|
||||
pageContent.requestFullscreen();
|
||||
DesignerMove.requestFullscreen(pageContent);
|
||||
} else {
|
||||
$img.attr('src', $img.data('enter'))
|
||||
.attr('title', $span.data('enter'));
|
||||
@ -2077,6 +2097,8 @@ const DesignerMove = {
|
||||
clear: clear,
|
||||
rect: rect,
|
||||
toggleFullscreen: toggleFullscreen,
|
||||
fullscreenEnabled: fullscreenEnabled,
|
||||
requestFullscreen: requestFullscreen,
|
||||
addTableToTablesList: addTableToTablesList,
|
||||
displayModal: displayModal,
|
||||
addOtherDbTables: addOtherDbTables,
|
||||
|
||||
@ -8,7 +8,8 @@ import {
|
||||
getCellValue,
|
||||
stringifyJSON,
|
||||
toggleDatepickerIfInvalid,
|
||||
updateCode
|
||||
updateCode,
|
||||
userAgent
|
||||
} from './modules/functions.ts';
|
||||
import { CommonParams } from './modules/common.ts';
|
||||
import highlightSql from './modules/sql-highlight.ts';
|
||||
@ -277,7 +278,7 @@ const makeGrid = function (t, enableResize = undefined, enableReorder = undefine
|
||||
for (var n = 0, l = $firstRowCols.length; n < l; n++) {
|
||||
var $col = $($firstRowCols[n]);
|
||||
var colWidth;
|
||||
if (navigator.userAgent.toLowerCase().indexOf('safari') !== -1) {
|
||||
if (userAgent().toLowerCase().indexOf('safari') !== -1) {
|
||||
colWidth = $col.outerWidth();
|
||||
} else {
|
||||
colWidth = $col.outerWidth(true);
|
||||
@ -301,6 +302,20 @@ const makeGrid = function (t, enableResize = undefined, enableReorder = undefine
|
||||
$(g.cRsz).css('height', $(g.t).height());
|
||||
},
|
||||
|
||||
/**
|
||||
* Clears the current cell edit state, internal flags,
|
||||
* and any pending save request.
|
||||
*/
|
||||
resetGridEditState: function () {
|
||||
g.isCellEditActive = false;
|
||||
g.isEditCellTextEditable = false;
|
||||
g.currentEditCell = null;
|
||||
g.wasEditedCellNull = false;
|
||||
g.isCellEdited = false;
|
||||
g.isSaving = false;
|
||||
g.lastXHR = null;
|
||||
},
|
||||
|
||||
/**
|
||||
* Shift column from index oldn to newn.
|
||||
*
|
||||
@ -2823,6 +2838,9 @@ const makeGrid = function (t, enableResize = undefined, enableReorder = undefine
|
||||
// some adjustment
|
||||
$(t).removeClass('data');
|
||||
$(g.gDiv).addClass('data');
|
||||
/* Store the grid controller instance on the table element so it can be accessed later by other modules
|
||||
(e.g. during AJAX teardown) without exposing the grid object as a global variable.*/
|
||||
$(t).data('pmaGrid', g);
|
||||
g.initCellSelection();
|
||||
};
|
||||
|
||||
|
||||
@ -64,6 +64,19 @@ export function addNoCacheToAjaxRequests (options: JQuery.AjaxSettings, original
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an empty string for user-agent, if undefined
|
||||
*/
|
||||
export function userAgent (): string {
|
||||
try {
|
||||
return navigator.userAgent;
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
|
||||
return '';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a date/time picker to an element
|
||||
*
|
||||
|
||||
@ -38,7 +38,8 @@ import {
|
||||
teardownIdleEvent,
|
||||
teardownRecentFavoriteTables,
|
||||
teardownSortLinkMouseEvent,
|
||||
teardownSqlQueryEditEvents
|
||||
teardownSqlQueryEditEvents,
|
||||
userAgent,
|
||||
} from '../functions.ts';
|
||||
import handleCreateViewModal from './handleCreateViewModal.ts';
|
||||
|
||||
@ -93,7 +94,7 @@ export function onloadFunctions () {
|
||||
/**
|
||||
* Add attribute to text boxes for iOS devices (based on bugID: 3508912)
|
||||
*/
|
||||
if (navigator.userAgent.match(/(iphone|ipod|ipad)/i)) {
|
||||
if (userAgent().match(/(iphone|ipod|ipad)/i)) {
|
||||
$('input[type=text]').attr('autocapitalize', 'off').attr('autocorrect', 'off');
|
||||
}
|
||||
|
||||
|
||||
@ -462,9 +462,9 @@ export default function highlightSql ($base) {
|
||||
var $pre = $sql.closest('pre');
|
||||
/* We only care about visible elements to avoid double processing */
|
||||
if ($sql.is(':visible')) {
|
||||
if (typeof window.CodeMirror !== 'undefined') {
|
||||
var $highlight = $('<div class="sql-highlight cm-s-default"></div>');
|
||||
$pre.append($highlight);
|
||||
if (typeof window.CodeMirror !== 'undefined') {
|
||||
// @ts-ignore
|
||||
window.CodeMirror.runMode($sql.text(), 'text/x-mysql', $highlight[0]);
|
||||
$sql.hide();
|
||||
|
||||
@ -505,6 +505,13 @@ AJAX.registerTeardown('table/change.js', function () {
|
||||
$(document).off('click', 'input.checkbox_null');
|
||||
$('select[name="submit_type"]').off('change');
|
||||
$(document).off('change', '#insert_rows');
|
||||
|
||||
// Reset grid edit state
|
||||
var grid = $('table.table_results').data('pmaGrid');
|
||||
|
||||
if (grid && typeof grid.resetGridEditState === 'function') {
|
||||
grid.resetGridEditState();
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
|
||||
@ -343,6 +343,37 @@ final class HomeController implements InvocableController
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if user does not have defined query encryption key and it is being used.
|
||||
*/
|
||||
if ($this->config->config->URLQueryEncryption) {
|
||||
$encryptionKeyLength = 0;
|
||||
$encryptionKeyLength = mb_strlen($this->config->config->URLQueryEncryptionSecretKey, '8bit');
|
||||
|
||||
if ($encryptionKeyLength < SODIUM_CRYPTO_SECRETBOX_KEYBYTES) {
|
||||
$this->errors[] = [
|
||||
'message' => __(
|
||||
'The configuration file needs a valid key for query encryption.'
|
||||
. ' A temporary key was automatically generated for you.'
|
||||
. ' Please refer to the [doc@cfg_URLQueryEncryptionSecretKey]documentation[/doc].',
|
||||
),
|
||||
'severity' => 'warning',
|
||||
];
|
||||
} elseif ($encryptionKeyLength > SODIUM_CRYPTO_SECRETBOX_KEYBYTES) {
|
||||
$this->errors[] = [
|
||||
'message' => sprintf(
|
||||
__(
|
||||
'The query encryption key in the configuration file is longer than necessary.'
|
||||
. ' It should only be %d bytes long.'
|
||||
. ' Please refer to the [doc@cfg_URLQueryEncryptionSecretKey]documentation[/doc].',
|
||||
),
|
||||
SODIUM_CRYPTO_SECRETBOX_KEYBYTES,
|
||||
),
|
||||
'severity' => 'warning',
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check for existence of config directory which should not exist in
|
||||
* production environment.
|
||||
|
||||
@ -692,7 +692,10 @@ final class JavaScriptMessagesController implements InvocableController
|
||||
'strHide' => __('Hide'),
|
||||
'strShow' => __('Show'),
|
||||
'strStructure' => __('Structure'),
|
||||
'strFullscreenRequestDenied' => __('The fullscreen request was denied.'),
|
||||
'strFullscreenRequestDenied' => __(
|
||||
'The fullscreen request was denied because'
|
||||
. ' the Fullscreen API is disabled by user preference in the browser.',
|
||||
),
|
||||
|
||||
'strMonthNameJan' => _pgettext('Month name', 'January'),
|
||||
'strMonthNameFeb' => _pgettext('Month name', 'February'),
|
||||
|
||||
@ -75,7 +75,7 @@ class ErrorReport
|
||||
'browser_version' => $userAgentParser->getUserBrowserVersion(),
|
||||
'user_os' => $userAgentParser->getClientPlatform(),
|
||||
'server_software' => $_SERVER['SERVER_SOFTWARE'] ?? null,
|
||||
'user_agent_string' => $_SERVER['HTTP_USER_AGENT'],
|
||||
'user_agent_string' => $_SERVER['HTTP_USER_AGENT'] ?? null,
|
||||
'locale' => $this->config->getCookie('pma_lang'),
|
||||
'configuration_storage' => $relationParameters->db === null ? 'disabled' : 'enabled',
|
||||
'php_version' => PHP_VERSION,
|
||||
|
||||
@ -217,10 +217,12 @@ class Header
|
||||
$themeManager = ContainerBuilder::getContainer()->get(ThemeManager::class);
|
||||
$theme = $themeManager->theme;
|
||||
$scripts = $this->getScripts();
|
||||
$userAgent = Core::getEnv('HTTP_USER_AGENT');
|
||||
|
||||
// The user preferences have been merged at this point
|
||||
// so we can conditionally add CodeMirror, other scripts and settings
|
||||
if ($this->config->config->CodemirrorEnable) {
|
||||
// See #20159, why we need to check for HTTP_USER_AGENT here
|
||||
if ($this->config->config->CodemirrorEnable && $userAgent !== '') {
|
||||
$scripts->addFile('vendor/codemirror/lib/codemirror.js');
|
||||
$scripts->addFile('vendor/codemirror/mode/sql/sql.js');
|
||||
$scripts->addFile('vendor/codemirror/addon/runmode/runmode.js');
|
||||
|
||||
@ -565,7 +565,7 @@ class Generator
|
||||
if (
|
||||
! empty($config->settings['SQLQuery']['Refresh'])
|
||||
&& Sql::$showAsPhp === null // 'Submit query' does the same
|
||||
&& preg_match('@^(SELECT|SHOW)[[:space:]]+@i', $sqlQuery) === 1
|
||||
&& preg_match('@^(ANALYZE|EXPLAIN|SELECT|SHOW)[[:space:]]+@i', $sqlQuery) === 1
|
||||
) {
|
||||
$refreshLink = Url::getFromRoute('/sql', $urlParams);
|
||||
$refreshLink = '<div class="col-auto">'
|
||||
@ -954,6 +954,7 @@ class Generator
|
||||
// Has as sql_query without a signature, to be accepted it needs to be sent using POST
|
||||
str_contains($url, 'sql_query=') && ! str_contains($url, 'sql_signature=')
|
||||
)
|
||||
|| $config->config->URLQueryEncryption
|
||||
|| str_contains($url, 'view[as]=');
|
||||
if ($respectUrlLengthLimit && $isDataPostFormatSupported) {
|
||||
$parts = explode('?', $url, 2);
|
||||
|
||||
@ -847,7 +847,8 @@ final class Import
|
||||
if ($analyses !== null) {
|
||||
$isVarchar = $analyses[$tableIndex][$columnIndex]->type === ColumnType::Varchar;
|
||||
} else {
|
||||
$isVarchar = ! is_numeric($row[$columnIndex]);
|
||||
$isVarchar = ! is_numeric($row[$columnIndex])
|
||||
&& ! preg_match('/^0x[0-9a-f]+$/', (string) $row[$columnIndex]);
|
||||
}
|
||||
|
||||
/* Don't put quotes around NULL fields */
|
||||
|
||||
@ -21,6 +21,7 @@ use PhpMyAdmin\Properties\Options\Items\TextPropertyItem;
|
||||
use PhpMyAdmin\Properties\Plugins\ExportPluginProperties;
|
||||
|
||||
use function __;
|
||||
use function bin2hex;
|
||||
use function implode;
|
||||
use function is_string;
|
||||
use function str_replace;
|
||||
@ -139,6 +140,7 @@ class ExportCsv extends ExportPlugin
|
||||
array $aliases = [],
|
||||
): void {
|
||||
$result = $this->dbi->query($sqlQuery, ConnectionType::User, DatabaseInterface::QUERY_UNBUFFERED);
|
||||
$fieldsMeta = $this->dbi->getFieldsMeta($result);
|
||||
|
||||
$charsNeedingEnclosure = $this->separator . $this->enclosed . $this->terminated;
|
||||
|
||||
@ -165,7 +167,7 @@ class ExportCsv extends ExportPlugin
|
||||
// Format the data
|
||||
while ($row = $result->fetchRow()) {
|
||||
$insertValues = [];
|
||||
foreach ($row as $field) {
|
||||
foreach ($row as $j => $field) {
|
||||
if ($field === null) {
|
||||
$insertValues[] = $this->null;
|
||||
continue;
|
||||
@ -176,6 +178,11 @@ class ExportCsv extends ExportPlugin
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($fieldsMeta[$j]->isMappedTypeGeometry || $fieldsMeta[$j]->isBinary) {
|
||||
$insertValues[] = '0x' . bin2hex($row[$j] ?? '');
|
||||
continue;
|
||||
}
|
||||
|
||||
// remove CRLF characters within field
|
||||
if ($this->removeCrLf) {
|
||||
$field = str_replace(["\r", "\n"], '', $field);
|
||||
|
||||
@ -28,6 +28,8 @@ use function __;
|
||||
use function addcslashes;
|
||||
use function array_keys;
|
||||
use function array_values;
|
||||
use function assert;
|
||||
use function bin2hex;
|
||||
use function in_array;
|
||||
use function is_string;
|
||||
use function mb_strpos;
|
||||
@ -272,8 +274,10 @@ class ExportLatex extends ExportPlugin
|
||||
$tableAlias = $this->getTableAlias($aliases, $db, $table);
|
||||
|
||||
$result = $this->dbi->tryQuery($sqlQuery, ConnectionType::User, DatabaseInterface::QUERY_UNBUFFERED);
|
||||
assert($result !== false);
|
||||
|
||||
$columnsCnt = $result->numFields();
|
||||
$fieldsMeta = $this->dbi->getFieldsMeta($result);
|
||||
$columns = [];
|
||||
$columnsAlias = [];
|
||||
foreach ($result->getFieldNames() as $i => $colAs) {
|
||||
@ -350,7 +354,13 @@ class ExportLatex extends ExportPlugin
|
||||
/** @infection-ignore-all */
|
||||
for ($i = 0; $i < $columnsCnt; $i++) {
|
||||
if ($record[$columns[$i]] !== null) {
|
||||
if ($fieldsMeta[$i]->isMappedTypeGeometry || $fieldsMeta[$i]->isBinary) {
|
||||
$columnValue = self::texEscape(
|
||||
'0x' . bin2hex($record[$columns[$i]]),
|
||||
);
|
||||
} else {
|
||||
$columnValue = self::texEscape($record[$columns[$i]]);
|
||||
}
|
||||
} else {
|
||||
$columnValue = $this->null;
|
||||
}
|
||||
|
||||
@ -23,6 +23,7 @@ use PhpMyAdmin\Util;
|
||||
|
||||
use function __;
|
||||
use function array_values;
|
||||
use function bin2hex;
|
||||
use function htmlspecialchars;
|
||||
use function str_repeat;
|
||||
|
||||
@ -226,6 +227,7 @@ class ExportMediawiki extends ExportPlugin
|
||||
// Get the table data from the database
|
||||
$result = $this->dbi->query($sqlQuery, ConnectionType::User, DatabaseInterface::QUERY_UNBUFFERED);
|
||||
$fieldsCnt = $result->numFields();
|
||||
$fieldsMeta = $this->dbi->getFieldsMeta($result);
|
||||
|
||||
while ($row = $result->fetchRow()) {
|
||||
$output .= '|-' . $this->exportCRLF();
|
||||
@ -233,6 +235,12 @@ class ExportMediawiki extends ExportPlugin
|
||||
// Use '|' for separating table columns
|
||||
/** @infection-ignore-all */
|
||||
for ($i = 0; $i < $fieldsCnt; ++$i) {
|
||||
if (! isset($row[$i])) {
|
||||
$row[$i] = 'NULL';
|
||||
} elseif ($fieldsMeta[$i]->isMappedTypeGeometry || $fieldsMeta[$i]->isBinary) {
|
||||
$row[$i] = '0x' . bin2hex($row[$i]);
|
||||
}
|
||||
|
||||
$output .= ' | ' . $row[$i] . $this->exportCRLF();
|
||||
}
|
||||
}
|
||||
|
||||
@ -21,6 +21,7 @@ use PhpMyAdmin\Util;
|
||||
use PhpMyAdmin\Version;
|
||||
|
||||
use function __;
|
||||
use function bin2hex;
|
||||
use function preg_match;
|
||||
use function preg_replace;
|
||||
use function strtr;
|
||||
@ -127,6 +128,7 @@ class ExportPhparray extends ExportPlugin
|
||||
$result = $this->dbi->query($sqlQuery, ConnectionType::User, DatabaseInterface::QUERY_UNBUFFERED);
|
||||
|
||||
$columnsCnt = $result->numFields();
|
||||
$fieldsMeta = $this->dbi->getFieldsMeta($result);
|
||||
$columns = [];
|
||||
foreach ($result->getFieldNames() as $i => $colAs) {
|
||||
$colAs = $this->getColumnAlias($aliases, $db, $table, $colAs);
|
||||
@ -171,6 +173,10 @@ class ExportPhparray extends ExportPlugin
|
||||
|
||||
/** @infection-ignore-all */
|
||||
for ($i = 0; $i < $columnsCnt; $i++) {
|
||||
if ($record[$i] !== null && ($fieldsMeta[$i]->isMappedTypeGeometry || $fieldsMeta[$i]->isBinary)) {
|
||||
$record[$i] = '0x' . bin2hex($record[$i]);
|
||||
}
|
||||
|
||||
$buffer .= var_export($columns[$i], true)
|
||||
. ' => ' . var_export($record[$i], true)
|
||||
. ($i + 1 >= $columnsCnt ? '' : ',');
|
||||
|
||||
@ -25,6 +25,7 @@ use PhpMyAdmin\Triggers\Triggers;
|
||||
use PhpMyAdmin\Util;
|
||||
|
||||
use function __;
|
||||
use function bin2hex;
|
||||
use function htmlspecialchars;
|
||||
use function in_array;
|
||||
use function is_string;
|
||||
@ -143,6 +144,7 @@ class ExportTexytext extends ExportPlugin
|
||||
* Gets the data from the database
|
||||
*/
|
||||
$result = $this->dbi->query($sqlQuery, ConnectionType::User, DatabaseInterface::QUERY_UNBUFFERED);
|
||||
$fieldsMeta = $this->dbi->getFieldsMeta($result);
|
||||
|
||||
// If required, get fields name at the first line
|
||||
if ($this->columns) {
|
||||
@ -160,11 +162,15 @@ class ExportTexytext extends ExportPlugin
|
||||
// Format the data
|
||||
while ($row = $result->fetchRow()) {
|
||||
$textOutput = '';
|
||||
foreach ($row as $field) {
|
||||
foreach ($row as $j => $field) {
|
||||
if ($field === null) {
|
||||
$value = $this->null;
|
||||
} elseif ($field !== '') {
|
||||
$value = $field;
|
||||
|
||||
if ($fieldsMeta[$j]->isMappedTypeGeometry || $fieldsMeta[$j]->isBinary) {
|
||||
$value = '0x' . bin2hex($value);
|
||||
}
|
||||
} else {
|
||||
$value = ' ';
|
||||
}
|
||||
|
||||
@ -25,6 +25,7 @@ use PhpMyAdmin\Util;
|
||||
use PhpMyAdmin\Version;
|
||||
|
||||
use function __;
|
||||
use function bin2hex;
|
||||
use function htmlspecialchars;
|
||||
use function mb_substr;
|
||||
use function rtrim;
|
||||
@ -402,6 +403,7 @@ class ExportXml extends ExportPlugin
|
||||
$result = $this->dbi->query($sqlQuery, ConnectionType::User, DatabaseInterface::QUERY_UNBUFFERED);
|
||||
|
||||
$columnsCnt = $result->numFields();
|
||||
$fieldsMeta = $this->dbi->getFieldsMeta($result);
|
||||
$columns = $result->getFieldNames();
|
||||
|
||||
$buffer = ' <!-- ' . __('Table') . ' '
|
||||
@ -418,6 +420,8 @@ class ExportXml extends ExportPlugin
|
||||
// the XML structure
|
||||
if (! isset($record[$i])) {
|
||||
$record[$i] = 'NULL';
|
||||
} elseif ($fieldsMeta[$i]->isMappedTypeGeometry || $fieldsMeta[$i]->isBinary) {
|
||||
$record[$i] = '0x' . bin2hex($record[$i]);
|
||||
}
|
||||
|
||||
$buffer .= ' <column name="'
|
||||
|
||||
@ -21,6 +21,7 @@ use PhpMyAdmin\Properties\Plugins\ExportPluginProperties;
|
||||
|
||||
use function __;
|
||||
use function array_key_exists;
|
||||
use function bin2hex;
|
||||
use function is_numeric;
|
||||
use function str_replace;
|
||||
|
||||
@ -130,6 +131,10 @@ class ExportYaml extends ExportPlugin
|
||||
continue;
|
||||
}
|
||||
|
||||
if ($fieldsMeta[$i]->isMappedTypeGeometry || $fieldsMeta[$i]->isBinary) {
|
||||
$record[$i] = '0x' . bin2hex($record[$i]);
|
||||
}
|
||||
|
||||
$isNotString = isset($fieldsMeta[$i]) && $fieldsMeta[$i]->isNotType(FieldMetadata::TYPE_STRING);
|
||||
if (is_numeric($record[$i]) && $isNotString) {
|
||||
$buffer .= ' ' . $columns[$i] . ': ' . $record[$i] . "\n";
|
||||
|
||||
@ -184,8 +184,9 @@ class Pdf extends PdfLib
|
||||
* Generate table
|
||||
*
|
||||
* @param int|float $lineheight Height of line
|
||||
* @param list<FieldMetadata> $fields meta info for fields in $this->results
|
||||
*/
|
||||
public function morepagestable(int|float $lineheight = 8): void
|
||||
public function morepagestable(int|float $lineheight, array $fields): void
|
||||
{
|
||||
// some things to set and 'remember'
|
||||
$l = $this->lMargin;
|
||||
@ -212,6 +213,16 @@ class Pdf extends PdfLib
|
||||
$this->page = $currpage;
|
||||
$this->setXY($l, $h);
|
||||
if ($this->tablewidths[$col] > 0) {
|
||||
if ($txt !== null) {
|
||||
if ($fields[$col]->isType(FieldMetadata::TYPE_GEOMETRY)) {
|
||||
$txt = '[GEOMETRY]';
|
||||
}
|
||||
|
||||
if ($fields[$col]->isType(FieldMetadata::TYPE_BLOB) || $fields[$col]->isBinary()) {
|
||||
$txt = '[BLOB]';
|
||||
}
|
||||
}
|
||||
|
||||
$this->MultiCell($this->tablewidths[$col], $lineheight, $txt ?? 'NULL', 0, $this->colAlign[$col]);
|
||||
$l += $this->tablewidths[$col];
|
||||
}
|
||||
@ -690,7 +701,7 @@ class Pdf extends PdfLib
|
||||
}
|
||||
|
||||
/**
|
||||
* @todo do not deactivate completely the display
|
||||
* do not deactivate completely the display
|
||||
* but show the field's name and [BLOB]
|
||||
*/
|
||||
if ($fields[$i]->isBinary()) {
|
||||
@ -765,11 +776,12 @@ class Pdf extends PdfLib
|
||||
// Pass 2
|
||||
|
||||
$this->results = $dbi->query($query, ConnectionType::User, DatabaseInterface::QUERY_UNBUFFERED);
|
||||
$fields = $dbi->getFieldsMeta($this->results);
|
||||
$this->setY($this->tMargin);
|
||||
$this->AddPage();
|
||||
$this->setFont(PdfLib::PMA_PDF_FONT, '', 9);
|
||||
// phpcs:ignore Squiz.NamingConventions.ValidVariableName.MemberNotCamelCaps
|
||||
$this->morepagestable($this->FontSizePt);
|
||||
$this->morepagestable($this->FontSizePt, $fields);
|
||||
}
|
||||
|
||||
public function setTitleFontSize(int $titleFontSize): void
|
||||
|
||||
@ -16,15 +16,13 @@ class ChangePasswordTest extends TestBase
|
||||
/**
|
||||
* Create a test database for this test class
|
||||
*/
|
||||
protected static bool $createDatabase = false;
|
||||
protected bool $createDatabase = false;
|
||||
|
||||
/**
|
||||
* Tests the changing of the password
|
||||
*/
|
||||
public function testChangePassword(): void
|
||||
{
|
||||
$this->login();
|
||||
|
||||
$e = $this->waitForElement('id', 'change_password_anchor');
|
||||
$e->click();
|
||||
|
||||
|
||||
@ -20,7 +20,6 @@ class CreateDropDatabaseTest extends TestBase
|
||||
|
||||
/* TODO: For now this tests needs superuser for deleting database */
|
||||
$this->skipIfNotSuperUser();
|
||||
$this->login();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -17,7 +17,7 @@ class CreateRemoveUserTest extends TestBase
|
||||
/**
|
||||
* Create a test database for this test class
|
||||
*/
|
||||
protected static bool $createDatabase = false;
|
||||
protected bool $createDatabase = false;
|
||||
|
||||
/**
|
||||
* Username for the user
|
||||
@ -39,7 +39,6 @@ class CreateRemoveUserTest extends TestBase
|
||||
$this->skipIfNotSuperUser();
|
||||
$this->txtUsername = 'test_user_' . bin2hex(random_bytes(4));
|
||||
$this->txtPassword = 'abc_123';
|
||||
$this->login();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -34,7 +34,7 @@ class EventsTest extends TestBase
|
||||
. 'INSERT INTO `test_table` (val) VALUES (2);'
|
||||
. 'SET GLOBAL event_scheduler="ON";',
|
||||
);
|
||||
$this->login();
|
||||
|
||||
$this->navigateDatabase($this->databaseName);
|
||||
|
||||
// Let the Database page load
|
||||
|
||||
@ -12,16 +12,6 @@ use PHPUnit\Framework\Attributes\Large;
|
||||
#[Large]
|
||||
class OperationsTest extends TestBase
|
||||
{
|
||||
/**
|
||||
* setUp function
|
||||
*/
|
||||
protected function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
$this->login();
|
||||
}
|
||||
|
||||
private function getToDBOperations(): void
|
||||
{
|
||||
$this->gotoHomepage();
|
||||
|
||||
@ -49,8 +49,6 @@ class ProceduresTest extends TestBase
|
||||
. ');',
|
||||
);
|
||||
|
||||
$this->login();
|
||||
|
||||
$this->navigateDatabase($this->databaseName);
|
||||
$this->expandMore();
|
||||
}
|
||||
|
||||
@ -34,7 +34,6 @@ class StructureTest extends TestBase
|
||||
. 'INSERT INTO `test_table` (val) VALUES (2);',
|
||||
);
|
||||
|
||||
$this->login();
|
||||
$this->navigateDatabase($this->databaseName);
|
||||
|
||||
// Let the Database page load
|
||||
|
||||
@ -30,8 +30,6 @@ class ExportTest extends TestBase
|
||||
. ');'
|
||||
. 'INSERT INTO `test_table` (val) VALUES (2);',
|
||||
);
|
||||
|
||||
$this->login();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -11,16 +11,6 @@ use PHPUnit\Framework\Attributes\Large;
|
||||
#[Large]
|
||||
class ImportTest extends TestBase
|
||||
{
|
||||
/**
|
||||
* setUp function
|
||||
*/
|
||||
protected function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
$this->login();
|
||||
}
|
||||
|
||||
/**
|
||||
* Test for server level import
|
||||
*/
|
||||
|
||||
@ -14,7 +14,12 @@ class LoginTest extends TestBase
|
||||
/**
|
||||
* Create a test database for this test class
|
||||
*/
|
||||
protected static bool $createDatabase = false;
|
||||
protected bool $createDatabase = false;
|
||||
|
||||
/**
|
||||
* Login before starting this test
|
||||
*/
|
||||
protected bool $login = false;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
@ -28,7 +33,6 @@ class LoginTest extends TestBase
|
||||
*/
|
||||
public function testSuccessfulLogin(): void
|
||||
{
|
||||
$this->login();
|
||||
$this->waitForElement('xpath', '//*[@id="server-breadcrumb"]');
|
||||
self::assertTrue($this->isSuccessLogin());
|
||||
$this->logOutIfLoggedIn();
|
||||
|
||||
@ -28,7 +28,6 @@ class NormalizationTest extends TestBase
|
||||
. ');',
|
||||
);
|
||||
|
||||
$this->login();
|
||||
$this->navigateTable('test_table');
|
||||
$this->waitForElement('xpath', "(//a[contains(., 'Structure')])")->click();
|
||||
|
||||
|
||||
@ -16,7 +16,7 @@ class ServerSettingsTest extends TestBase
|
||||
/**
|
||||
* Create a test database for this test class
|
||||
*/
|
||||
protected static bool $createDatabase = false;
|
||||
protected bool $createDatabase = false;
|
||||
|
||||
/**
|
||||
* setUp function
|
||||
@ -25,7 +25,6 @@ class ServerSettingsTest extends TestBase
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
$this->login();
|
||||
$this->expandMore();
|
||||
$this->waitForElement('partialLinkText', 'Settings')->click();
|
||||
$this->waitAjax();
|
||||
|
||||
@ -25,7 +25,6 @@ class SqlQueryTest extends TestBase
|
||||
. ');'
|
||||
. 'INSERT INTO `test_table` (val) VALUES (2), (3), (4), (5);',
|
||||
);
|
||||
$this->login();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -34,7 +34,6 @@ class BrowseTest extends TestBase
|
||||
. " (3, 'Abcd', '2012-01-20 02:00:02');",
|
||||
);
|
||||
|
||||
$this->login();
|
||||
$this->navigateTable('test_table');
|
||||
|
||||
$this->waitAjax();
|
||||
|
||||
@ -18,7 +18,6 @@ class CreateTest extends TestBase
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
$this->login();
|
||||
$this->navigateDatabase($this->databaseName);
|
||||
}
|
||||
|
||||
|
||||
@ -30,7 +30,6 @@ class InsertTest extends TestBase
|
||||
. ');',
|
||||
);
|
||||
|
||||
$this->login();
|
||||
$this->navigateTable('test_table');
|
||||
}
|
||||
|
||||
|
||||
@ -33,7 +33,6 @@ class OperationsTest extends TestBase
|
||||
. 'INSERT INTO test_table (val, val2) VALUES (33, 44);',
|
||||
);
|
||||
|
||||
$this->login();
|
||||
$this->navigateTable('test_table');
|
||||
|
||||
$this->waitAjax();
|
||||
|
||||
@ -29,7 +29,6 @@ class StructureTest extends TestBase
|
||||
. ');',
|
||||
);
|
||||
|
||||
$this->login();
|
||||
$this->navigateTable('test_table');
|
||||
|
||||
$this->waitForElement('xpath', "(//a[contains(., 'Structure')])")->click();
|
||||
|
||||
@ -84,7 +84,12 @@ abstract class TestBase extends TestCase
|
||||
/**
|
||||
* Create a test database for this test class
|
||||
*/
|
||||
protected static bool $createDatabase = true;
|
||||
protected bool $createDatabase = true;
|
||||
|
||||
/**
|
||||
* Login before starting this test
|
||||
*/
|
||||
protected bool $login = true;
|
||||
|
||||
/**
|
||||
* Did the test create the phpMyAdmin storage database ?
|
||||
@ -135,8 +140,12 @@ abstract class TestBase extends TestCase
|
||||
$this->navigateTo('');
|
||||
$this->webDriver->manage()->window()->maximize();
|
||||
|
||||
if (! static::$createDatabase) {
|
||||
// Stop here, we were not asked to create a database
|
||||
if ($this->login) {
|
||||
$this->login();
|
||||
}
|
||||
|
||||
if (! $this->createDatabase) {
|
||||
// Stop here, we where not asked to create a database
|
||||
return;
|
||||
}
|
||||
|
||||
@ -152,7 +161,7 @@ abstract class TestBase extends TestCase
|
||||
$this->dbQuery(
|
||||
'CREATE DATABASE IF NOT EXISTS `' . $this->databaseName . '`; USE `' . $this->databaseName . '`;',
|
||||
);
|
||||
static::$createDatabase = true;
|
||||
$this->createDatabase = true;
|
||||
}
|
||||
|
||||
public function getDbPrefix(): string
|
||||
@ -1085,7 +1094,7 @@ abstract class TestBase extends TestCase
|
||||
*/
|
||||
protected function tearDown(): void
|
||||
{
|
||||
if (static::$createDatabase) {
|
||||
if ($this->createDatabase) {
|
||||
$this->dbQuery('DROP DATABASE IF EXISTS `' . $this->databaseName . '`;');
|
||||
}
|
||||
|
||||
|
||||
@ -33,7 +33,6 @@ class TrackingTest extends TestBase
|
||||
. 'INSERT INTO `test_table` (val) VALUES (2), (3);',
|
||||
);
|
||||
|
||||
$this->login();
|
||||
$this->skipIfNotPMADB();
|
||||
|
||||
$this->navigateDatabase($this->databaseName);
|
||||
|
||||
@ -33,8 +33,6 @@ class TriggersTest extends TestBase
|
||||
. 'INSERT INTO `test_table2` (val) VALUES (2);',
|
||||
);
|
||||
|
||||
$this->login();
|
||||
|
||||
$this->navigateDatabase($this->databaseName);
|
||||
}
|
||||
|
||||
|
||||
@ -14,14 +14,7 @@ class XssTest extends TestBase
|
||||
/**
|
||||
* Create a test database for this test class
|
||||
*/
|
||||
protected static bool $createDatabase = false;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
$this->login();
|
||||
}
|
||||
protected bool $createDatabase = false;
|
||||
|
||||
/**
|
||||
* Tests the SQL query tab with a null query
|
||||
|
||||
85
tests/test_data/test.xml
Normal file
85
tests/test_data/test.xml
Normal file
@ -0,0 +1,85 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
- phpMyAdmin XML Dump
|
||||
- version 5.2.4-dev
|
||||
- https://www.phpmyadmin.net
|
||||
-
|
||||
- Host: localhost:3306
|
||||
- Generation Time: Feb 19, 2026 at 03:28 AM
|
||||
- Server version: 12.2.2-MariaDB
|
||||
- PHP Version: 7.2.34
|
||||
-->
|
||||
|
||||
<pma_xml_export version="1.0" xmlns:pma="https://www.phpmyadmin.net/some_doc_url/">
|
||||
<!--
|
||||
- Structure schemas
|
||||
-->
|
||||
<pma:structure_schemas>
|
||||
<pma:database name="test" collation="utf8mb4_general_ci" charset="utf8mb4">
|
||||
<pma:table name="test">
|
||||
CREATE TABLE `test` (
|
||||
`id` int(11) NOT NULL AUTO_INCREMENT,
|
||||
`binary` binary(16) NOT NULL,
|
||||
`name` varchar(20) NOT NULL,
|
||||
`shape` geometry DEFAULT NULL,
|
||||
PRIMARY KEY (`id`)
|
||||
) ENGINE=MyISAM AUTO_INCREMENT=9 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci;
|
||||
</pma:table>
|
||||
</pma:database>
|
||||
</pma:structure_schemas>
|
||||
|
||||
<!--
|
||||
- Database: 'test'
|
||||
-->
|
||||
<database name="test">
|
||||
<!-- Table test -->
|
||||
<table name="test">
|
||||
<column name="id">1</column>
|
||||
<column name="binary">0x10000000000000000000000000000000</column>
|
||||
<column name="name">POLYGON</column>
|
||||
<column name="shape">0x00000000010300000001000000040000000000000000405f40000000000000000000000000008063400000000000006940000000000040664000000000004057400000000000405f400000000000000000</column>
|
||||
</table>
|
||||
<table name="test">
|
||||
<column name="id">2</column>
|
||||
<column name="binary">0x20000000000000000000000000000000</column>
|
||||
<column name="name">MULTIPOLYGON</column>
|
||||
<column name="shape">0x00000000010600000002000000010300000001000000040000000000000000006140000000000000444000000000006062400000000000c0544000000000004064400000000000c0524000000000000061400000000000004440010300000001000000040000000000000000405a4000000000000000000000000000004c400000000000006940000000000080534000000000004057400000000000405a400000000000000000</column>
|
||||
</table>
|
||||
<table name="test">
|
||||
<column name="id">3</column>
|
||||
<column name="binary">0x30000000000000000000000000000000</column>
|
||||
<column name="name">MULTIPOINT</column>
|
||||
<column name="shape">0x0000000001040000000400000001010000000000000000405f400000000000004940010100000000000000008063400000000000406f40010100000000000000004066400000000000e0614001010000000000000000e065400000000000005440</column>
|
||||
</table>
|
||||
<table name="test">
|
||||
<column name="id">4</column>
|
||||
<column name="binary">0x40000000000000000000000000000000</column>
|
||||
<column name="name">MULTILINESTRING</column>
|
||||
<column name="shape">0x000000000105000000020000000102000000030000000000000000004240000000000080614000000000008047400000000000206d400000000000004f400000000000c052400102000000030000000000000000004240000000000000594000000000000031400000000000206d4000000000004066400000000000405740</column>
|
||||
</table>
|
||||
<table name="test">
|
||||
<column name="id">5</column>
|
||||
<column name="binary">0x50000000000000000000000000000000</column>
|
||||
<column name="name">POINT</column>
|
||||
<column name="shape">0x00000000010100000000000000000059400000000000406f40</column>
|
||||
</table>
|
||||
<table name="test">
|
||||
<column name="id">6</column>
|
||||
<column name="binary">0x60000000000000000000000000000000</column>
|
||||
<column name="name">LINESTRING</column>
|
||||
<column name="shape">0x0000000001020000000400000000000000008063400000000000003840000000000040664000000000000058400000000000606d4000000000000069400000000000a063400000000000c06140</column>
|
||||
</table>
|
||||
<table name="test">
|
||||
<column name="id">7</column>
|
||||
<column name="binary">0x70000000000000000000000000000000</column>
|
||||
<column name="name">GEOMETRYCOLLECTION</column>
|
||||
<column name="shape">0x000000000107000000030000000101000000000000000000594000000000000059400102000000050000000000000000000000000000000000000000000000000059400000000000005940000000000000694000000000000069400000000000c072400000000000c07240000000000000794000000000000079400103000000020000000500000000000000008041400000000000002440000000000000244000000000000034400000000000002e40000000000000444000000000008046400000000000804640000000000080414000000000000024400400000000000000000034400000000000003e40000000000080414000000000008041400000000000003e40000000000000344000000000000034400000000000003e40</column>
|
||||
</table>
|
||||
<table name="test">
|
||||
<column name="id">8</column>
|
||||
<column name="binary">0x80000000000000000000000000000000</column>
|
||||
<column name="name">TEST</column>
|
||||
<column name="shape">NULL</column>
|
||||
</table>
|
||||
</database>
|
||||
</pma_xml_export>
|
||||
@ -108,6 +108,24 @@ final class ImportXmlTest extends AbstractTestCase
|
||||
pma_bookmarktest (Structure) (Options)
|
||||
*/
|
||||
|
||||
//assert that all sql are executed
|
||||
self::assertSame(
|
||||
'CREATE DATABASE IF NOT EXISTS `phpmyadmintest` DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;'
|
||||
. 'USE `phpmyadmintest`;' . "\n"
|
||||
. 'CREATE TABLE IF NOT EXISTS `pma_bookmarktest` (' . "\n"
|
||||
. ' `id` int(11) NOT NULL AUTO_INCREMENT,' . "\n"
|
||||
. ' `dbase` varchar(255) COLLATE utf8_bin NOT NULL DEFAULT \'\',' . "\n"
|
||||
. ' `user` varchar(255) COLLATE utf8_bin NOT NULL DEFAULT \'\',' . "\n"
|
||||
. ' `label` varchar(255) CHARACTER SET utf8 NOT NULL DEFAULT \'\',' . "\n"
|
||||
. ' `query` text COLLATE utf8_bin NOT NULL,' . "\n"
|
||||
. ' PRIMARY KEY (`id`)' . "\n"
|
||||
. ') ENGINE=MyISAM AUTO_INCREMENT=2 DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT=\'Bookmarks\';' . "\n"
|
||||
. ' ;'
|
||||
. 'INSERT INTO `phpmyadmintest`.`pma_bookmarktest` (`id`, `dbase`, `user`, `label`, `query`) '
|
||||
. 'VALUES (, \'\', \'\', \'\', \'\');;',
|
||||
Current::$sqlQuery,
|
||||
);
|
||||
|
||||
self::assertStringContainsString(
|
||||
'The following structures have either been created or altered.',
|
||||
ImportSettings::$importNotice,
|
||||
@ -126,4 +144,50 @@ final class ImportXmlTest extends AbstractTestCase
|
||||
|
||||
return new ImportXml(new Import($dbiObject, new ResponseRenderer(), $config), $dbiObject, $config);
|
||||
}
|
||||
|
||||
/**
|
||||
* Test for doImport using second dataset
|
||||
*/
|
||||
#[RequiresPhpExtension('simplexml')]
|
||||
public function testDoImportDataset2(): void
|
||||
{
|
||||
$dbi = $this->getMockBuilder(DatabaseInterface::class)
|
||||
->disableOriginalConstructor()
|
||||
->getMock();
|
||||
|
||||
$importHandle = new File(ImportSettings::$importFile);
|
||||
$importHandle->open();
|
||||
|
||||
ImportSettings::$importFile = 'test/test_data/test.xml';
|
||||
|
||||
$importXml = $this->getImportXml($dbi);
|
||||
$importXml->doImport($importHandle);
|
||||
|
||||
self::assertSame(
|
||||
'CREATE DATABASE IF NOT EXISTS `phpmyadmintest` DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;'
|
||||
. 'USE `phpmyadmintest`;' . "\n"
|
||||
. 'CREATE TABLE IF NOT EXISTS `pma_bookmarktest` (' . "\n"
|
||||
. ' `id` int(11) NOT NULL AUTO_INCREMENT,' . "\n"
|
||||
. ' `dbase` varchar(255) COLLATE utf8_bin NOT NULL DEFAULT \'\',' . "\n"
|
||||
. ' `user` varchar(255) COLLATE utf8_bin NOT NULL DEFAULT \'\',' . "\n"
|
||||
. ' `label` varchar(255) CHARACTER SET utf8 NOT NULL DEFAULT \'\',' . "\n"
|
||||
. ' `query` text COLLATE utf8_bin NOT NULL,' . "\n"
|
||||
. ' PRIMARY KEY (`id`)' . "\n"
|
||||
. ') ENGINE=MyISAM AUTO_INCREMENT=2 DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT=\'Bookmarks\';' . "\n"
|
||||
. ' ;'
|
||||
. 'INSERT INTO `phpmyadmintest`.`pma_bookmarktest` (`id`, `dbase`, `user`, `label`, `query`) '
|
||||
. 'VALUES (, \'\', \'\', \'\', \'\');;',
|
||||
Current::$sqlQuery,
|
||||
);
|
||||
|
||||
self::assertStringContainsString(
|
||||
'The following structures have either been created or altered.',
|
||||
ImportSettings::$importNotice,
|
||||
);
|
||||
self::assertStringContainsString('Go to database: `test`', ImportSettings::$importNotice);
|
||||
self::assertStringContainsString('Edit settings for `test`', ImportSettings::$importNotice);
|
||||
self::assertStringContainsString('Go to table: `test`', ImportSettings::$importNotice);
|
||||
self::assertStringContainsString('Edit settings for `test`', ImportSettings::$importNotice);
|
||||
self::assertTrue(ImportSettings::$finished);
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user