src/Controllers/Import/ImportController.php
<?php
declare(strict_types=1);
namespace PhpMyAdmin\Controllers\Import;
use PhpMyAdmin\Bookmarks\Bookmark;
use PhpMyAdmin\Bookmarks\BookmarkRepository;
use PhpMyAdmin\Config;
use PhpMyAdmin\ConfigStorage\Relation;
use PhpMyAdmin\Controllers\InvocableController;
use PhpMyAdmin\Core;
use PhpMyAdmin\Current;
use PhpMyAdmin\DatabaseInterface;
use PhpMyAdmin\Encoding;
use PhpMyAdmin\File;
use PhpMyAdmin\Html\Generator;
use PhpMyAdmin\Http\Response;
use PhpMyAdmin\Http\ServerRequest;
use PhpMyAdmin\Import\Import;
use PhpMyAdmin\Import\ImportSettings;
use PhpMyAdmin\Message;
use PhpMyAdmin\MessageType;
use PhpMyAdmin\ParseAnalyze;
use PhpMyAdmin\Plugins\Import\ImportFormat;
use PhpMyAdmin\ResponseRenderer;
use PhpMyAdmin\Sql;
use PhpMyAdmin\Url;
use PhpMyAdmin\Util;
use PhpMyAdmin\Utils\ForeignKey;
use Throwable;
use Webmozart\Assert\Assert;
use function __;
use function _ngettext;
use function ini_get;
use function ini_parse_quantity;
use function ini_set;
use function is_array;
use function is_link;
use function is_numeric;
use function is_string;
use function is_uploaded_file;
use function mb_strlen;
use function min;
use function preg_match;
use function preg_quote;
use function preg_replace;
use function time;
final class ImportController implements InvocableController
{
public function __construct(
private readonly ResponseRenderer $response,
private readonly Import $import,
private readonly Sql $sql,
private readonly DatabaseInterface $dbi,
private readonly BookmarkRepository $bookmarkRepository,
) {
}
public function __invoke(ServerRequest $request): Response
{
$GLOBALS['goto'] ??= null;
$GLOBALS['display_query'] ??= null;
$GLOBALS['ajax_reload'] ??= null;
$GLOBALS['import_text'] ??= null;
$GLOBALS['message'] ??= null;
$GLOBALS['errorUrl'] ??= null;
$GLOBALS['urlParams'] ??= null;
$GLOBALS['error'] ??= null;
$GLOBALS['result'] ??= null;
ImportSettings::$charsetOfFile = (string) $request->getParsedBodyParam('charset_of_file');
$format = $request->getParsedBodyParam('format', '');
ImportSettings::$importType = (string) $request->getParsedBodyParam('import_type');
$GLOBALS['is_js_confirmed'] = $request->getParsedBodyParam('is_js_confirmed');
$GLOBALS['message_to_show'] = $request->getParsedBodyParam('message_to_show');
$GLOBALS['noplugin'] = $request->getParsedBodyParam('noplugin');
ImportSettings::$skipQueries = (int) $request->getParsedBodyParam('skip_queries');
ImportSettings::$localImportFile = (string) $request->getParsedBodyParam('local_import_file');
$GLOBALS['show_as_php'] = $request->getParsedBodyParam('show_as_php');
// reset import messages for ajax request
$_SESSION['Import_message']['message'] = null;
$_SESSION['Import_message']['go_back_url'] = null;
// default values
$GLOBALS['reload'] = false;
$GLOBALS['ajax_reload'] = [];
$GLOBALS['import_text'] = '';
// Are we just executing plain query or sql file?
// (eg. non import, but query box/window run)
if (! empty($GLOBALS['sql_query'])) {
// apply values for parameters
/** @var array<string, string>|null $parameters */
$parameters = $request->getParsedBodyParam('parameters');
if ($request->hasBodyParam('parameterized') && is_array($parameters)) {
foreach ($parameters as $parameter => $replacementValue) {
if (! is_numeric($replacementValue)) {
$replacementValue = $this->dbi->quoteString($replacementValue);
}
$quoted = preg_quote($parameter, '/');
// making sure that :param does not apply values to :param1
$GLOBALS['sql_query'] = preg_replace(
'/' . $quoted . '([^a-zA-Z0-9_])/',
$replacementValue . '${1}',
$GLOBALS['sql_query'],
);
// for parameters the appear at the end of the string
$GLOBALS['sql_query'] = preg_replace(
'/' . $quoted . '$/',
$replacementValue,
$GLOBALS['sql_query'],
);
}
}
// run SQL query
$GLOBALS['import_text'] = $GLOBALS['sql_query'];
ImportSettings::$importType = 'query';
$format = 'sql';
$_SESSION['sql_from_query_box'] = true;
// If there is a request to ROLLBACK when finished.
if ($request->hasBodyParam('rollback_query')) {
$this->import->handleRollbackRequest($GLOBALS['import_text']);
}
// refresh navigation and main panels
if (preg_match('/^(DROP)\s+(VIEW|TABLE|DATABASE|SCHEMA)\s+/i', $GLOBALS['sql_query'])) {
$GLOBALS['reload'] = true;
$GLOBALS['ajax_reload']['reload'] = true;
}
// refresh navigation panel only
if (preg_match('/^(CREATE|ALTER)\s+(VIEW|TABLE|DATABASE|SCHEMA)\s+/i', $GLOBALS['sql_query'])) {
$GLOBALS['ajax_reload']['reload'] = true;
}
// do a dynamic reload if table is RENAMED
// (by sending the instruction to the AJAX response handler)
if (
preg_match('/^RENAME\s+TABLE\s+(.*?)\s+TO\s+(.*?)($|;|\s)/i', $GLOBALS['sql_query'], $renameTableNames)
) {
$GLOBALS['ajax_reload']['reload'] = true;
$GLOBALS['ajax_reload']['table_name'] = Util::unQuote($renameTableNames[2]);
}
$GLOBALS['sql_query'] = '';
} elseif ($request->hasBodyParam('id_bookmark')) {
// run bookmark
ImportSettings::$importType = 'query';
$format = 'sql';
}
// If we didn't get any parameters, either user called this directly, or
// upload limit has been reached, let's assume the second possibility.
$getParams = $request->getQueryParams();
$postParams = $request->getParsedBody();
if ($postParams === [] && $getParams === []) {
$GLOBALS['message'] = Message::error(
__(
'You probably tried to upload a file that is too large. Please refer ' .
'to %sdocumentation%s for a workaround for this limit.',
),
);
$GLOBALS['message']->addParam('[doc@faq1-16]');
$GLOBALS['message']->addParam('[/doc]');
// so we can obtain the message
$_SESSION['Import_message']['message'] = $GLOBALS['message']->getDisplay();
$_SESSION['Import_message']['go_back_url'] = $GLOBALS['goto'];
$this->response->setRequestStatus(false);
$this->response->addJSON('message', $GLOBALS['message']);
return $this->response->response();
}
// Add console message id to response output
$consoleMessageId = $request->getParsedBodyParam('console_message_id');
if ($consoleMessageId !== null) {
$this->response->addJSON('console_message_id', $consoleMessageId);
}
Assert::string($format);
$importFormat = ImportFormat::tryFrom($format);
if ($importFormat === null) {
$this->response->setRequestStatus(false);
$this->response->addHTML(Message::error(__('Incorrect format parameter'))->getDisplay());
return $this->response->response();
}
if (Current::$table !== '' && Current::$database !== '') {
$GLOBALS['urlParams'] = ['db' => Current::$database, 'table' => Current::$table];
} elseif (Current::$database !== '') {
$GLOBALS['urlParams'] = ['db' => Current::$database];
} else {
$GLOBALS['urlParams'] = [];
}
// Create error and goto url
if (ImportSettings::$importType === 'table') {
$GLOBALS['goto'] = Url::getFromRoute('/table/import');
} elseif (ImportSettings::$importType === 'database') {
$GLOBALS['goto'] = Url::getFromRoute('/database/import');
} elseif (ImportSettings::$importType === 'server') {
$GLOBALS['goto'] = Url::getFromRoute('/server/import');
} elseif (empty($GLOBALS['goto']) || ! preg_match('@^index\.php$@i', $GLOBALS['goto'])) {
if (Current::$table !== '' && Current::$database !== '') {
$GLOBALS['goto'] = Url::getFromRoute('/table/structure');
} elseif (Current::$database !== '') {
$GLOBALS['goto'] = Url::getFromRoute('/database/structure');
} else {
$GLOBALS['goto'] = Url::getFromRoute('/server/sql');
}
}
$GLOBALS['errorUrl'] = $GLOBALS['goto'] . Url::getCommon($GLOBALS['urlParams'], '&');
$_SESSION['Import_message']['go_back_url'] = $GLOBALS['errorUrl'];
if (Current::$database !== '') {
$this->dbi->selectDb(Current::$database);
}
Util::setTimeLimit();
$config = Config::getInstance();
if (! empty($config->settings['MemoryLimit'])) {
ini_set('memory_limit', $config->settings['MemoryLimit']);
}
ImportSettings::$timestamp = time();
ImportSettings::$maximumTime = 0;
$maxExecutionTime = (int) ini_get('max_execution_time');
if ($request->hasBodyParam('allow_interrupt') && $maxExecutionTime >= 1) {
ImportSettings::$maximumTime = $maxExecutionTime - 1; // Give 1 second for phpMyAdmin to exit nicely
}
// set default values
ImportSettings::$timeoutPassed = false;
$GLOBALS['error'] = false;
ImportSettings::$readMultiply = 1;
ImportSettings::$finished = false;
ImportSettings::$offset = 0;
ImportSettings::$maxSqlLength = 0;
$GLOBALS['sql_query'] = '';
ImportSettings::$sqlQueryDisabled = false;
ImportSettings::$goSql = false;
ImportSettings::$executedQueries = 0;
ImportSettings::$runQuery = true;
ImportSettings::$charsetConversion = false;
$resetCharset = false;
ImportSettings::$message = 'Sorry an unexpected error happened!';
$GLOBALS['result'] = false;
// Bookmark Support: get a query back from bookmark if required
$idBookmark = (int) $request->getParsedBodyParam('id_bookmark');
$actionBookmark = (int) $request->getParsedBodyParam('action_bookmark');
if ($idBookmark !== 0) {
switch ($actionBookmark) {
case 0: // bookmarked query that have to be run
$bookmark = $this->bookmarkRepository->get(
$request->hasBodyParam('action_bookmark_all') ? null : $config->selectedServer['user'],
$idBookmark,
);
if (! $bookmark instanceof Bookmark) {
break;
}
$bookmarkVariables = $request->getParsedBodyParam('bookmark_variable');
if (is_array($bookmarkVariables)) {
$GLOBALS['import_text'] = $bookmark->applyVariables($bookmarkVariables);
} else {
$GLOBALS['import_text'] = $bookmark->getQuery();
}
// refresh navigation and main panels
if (preg_match('/^(DROP)\s+(VIEW|TABLE|DATABASE|SCHEMA)\s+/i', $GLOBALS['import_text'])) {
$GLOBALS['reload'] = true;
$GLOBALS['ajax_reload']['reload'] = true;
}
// refresh navigation panel only
if (preg_match('/^(CREATE|ALTER)\s+(VIEW|TABLE|DATABASE|SCHEMA)\s+/i', $GLOBALS['import_text'])) {
$GLOBALS['ajax_reload']['reload'] = true;
}
break;
case 1: // bookmarked query that have to be displayed
$bookmark = $this->bookmarkRepository->get($config->selectedServer['user'], $idBookmark);
if (! $bookmark instanceof Bookmark) {
break;
}
$GLOBALS['import_text'] = $bookmark->getQuery();
if ($request->isAjax()) {
$GLOBALS['message'] = Message::success(__('Showing bookmark'));
$this->response->setRequestStatus($GLOBALS['message']->isSuccess());
$this->response->addJSON('message', $GLOBALS['message']);
$this->response->addJSON('sql_query', $GLOBALS['import_text']);
$this->response->addJSON('action_bookmark', $actionBookmark);
return $this->response->response();
}
ImportSettings::$runQuery = false;
break;
case 2: // bookmarked query that have to be deleted
$bookmark = $this->bookmarkRepository->get($config->selectedServer['user'], $idBookmark);
if (! $bookmark instanceof Bookmark) {
break;
}
$bookmark->delete();
if ($request->isAjax()) {
$GLOBALS['message'] = Message::success(
__('The bookmark has been deleted.'),
);
$this->response->setRequestStatus($GLOBALS['message']->isSuccess());
$this->response->addJSON('message', $GLOBALS['message']);
$this->response->addJSON('action_bookmark', $actionBookmark);
$this->response->addJSON('id_bookmark', $idBookmark);
return $this->response->response();
}
ImportSettings::$runQuery = false;
$GLOBALS['error'] = true; // this is kind of hack to skip processing the query
break;
}
}
// Do no run query if we show PHP code
if (isset($GLOBALS['show_as_php'])) {
ImportSettings::$runQuery = false;
ImportSettings::$goSql = true;
}
// We can not read all at once, otherwise we can run out of memory
// Calculate value of the limit
$memoryLimit = (string) ini_get('memory_limit');
$memoryLimit = ini_parse_quantity($memoryLimit);
// 2 MB as default
if ($memoryLimit === 0) {
$memoryLimit = 2 * 1024 * 1024;
}
// In case no memory limit we work on 10MB chunks
if ($memoryLimit === -1) {
$memoryLimit = 10 * 1024 * 1024;
}
// Just to be sure, there might be lot of memory needed for uncompression
ImportSettings::$readLimit = $memoryLimit / 8;
// handle filenames
if (
isset($_FILES['import_file'])
&& is_array($_FILES['import_file'])
&& isset($_FILES['import_file']['name'], $_FILES['import_file']['tmp_name'])
&& is_string($_FILES['import_file']['name'])
&& is_string($_FILES['import_file']['tmp_name'])
) {
ImportSettings::$importFile = $_FILES['import_file']['tmp_name'];
ImportSettings::$importFileName = $_FILES['import_file']['name'];
}
if (ImportSettings::$localImportFile !== '' && $config->settings['UploadDir'] !== '') {
// sanitize $local_import_file as it comes from a POST
ImportSettings::$localImportFile = Core::securePath(ImportSettings::$localImportFile);
ImportSettings::$importFile = Util::userDir($config->settings['UploadDir'])
. ImportSettings::$localImportFile;
/**
* Do not allow symlinks to avoid security issues
* (user can create symlink to file they can not access,
* but phpMyAdmin can).
*/
if (@is_link(ImportSettings::$importFile)) {
ImportSettings::$importFile = 'none';
}
} elseif (empty(ImportSettings::$importFile) || ! is_uploaded_file(ImportSettings::$importFile)) {
ImportSettings::$importFile = 'none';
}
// Do we have file to import?
if (ImportSettings::$importFile !== 'none' && ! $GLOBALS['error']) {
/**
* Handle file compression
*/
$importHandle = new File(ImportSettings::$importFile);
$importHandle->checkUploadedFile();
if ($importHandle->isError()) {
/** @var Message $errorMessage */
$errorMessage = $importHandle->getError();
$importHandle->close();
$_SESSION['Import_message']['message'] = $errorMessage->getDisplay();
$this->response->setRequestStatus(false);
$this->response->addJSON('message', $errorMessage->getDisplay());
$this->response->addHTML($errorMessage->getDisplay());
return $this->response->response();
}
$importHandle->setDecompressContent(true);
$importHandle->open();
if ($importHandle->isError()) {
/** @var Message $errorMessage */
$errorMessage = $importHandle->getError();
$importHandle->close();
$_SESSION['Import_message']['message'] = $errorMessage->getDisplay();
$this->response->setRequestStatus(false);
$this->response->addJSON('message', $errorMessage->getDisplay());
$this->response->addHTML($errorMessage->getDisplay());
return $this->response->response();
}
} elseif (! $GLOBALS['error'] && empty($GLOBALS['import_text'])) {
$GLOBALS['message'] = Message::error(
__(
'No data was received to import. Either no file name was ' .
'submitted, or the file size exceeded the maximum size permitted ' .
'by your PHP configuration. See [doc@faq1-16]FAQ 1.16[/doc].',
),
);
$_SESSION['Import_message']['message'] = $GLOBALS['message']->getDisplay();
$this->response->setRequestStatus(false);
$this->response->addJSON('message', $GLOBALS['message']->getDisplay());
$this->response->addHTML($GLOBALS['message']->getDisplay());
return $this->response->response();
}
// Convert the file's charset if necessary
if (
Encoding::isSupported()
&& ImportSettings::$charsetOfFile !== '' && ImportSettings::$charsetOfFile !== 'utf-8'
) {
ImportSettings::$charsetConversion = true;
} elseif (ImportSettings::$charsetOfFile !== '' && ImportSettings::$charsetOfFile !== 'utf-8') {
$this->dbi->query('SET NAMES \'' . ImportSettings::$charsetOfFile . '\'');
// We can not show query in this case, it is in different charset
ImportSettings::$sqlQueryDisabled = true;
$resetCharset = true;
}
// Something to skip? (because timeout has passed)
if (! $GLOBALS['error'] && $request->hasBodyParam('skip')) {
$originalSkip = $skip = (int) $request->getParsedBodyParam('skip');
while ($skip > 0 && ! ImportSettings::$finished) {
$this->import->getNextChunk(
$importHandle ?? null,
min($skip, ImportSettings::$readLimit),
);
// Disable read progressivity, otherwise we eat all memory!
ImportSettings::$readMultiply = 1;
$skip -= ImportSettings::$readLimit;
}
unset($skip);
}
// This array contain the data like number of valid sql queries in the statement
// and complete valid sql statement (which affected for rows)
$queriesToBeExecuted = [];
if (! $GLOBALS['error']) {
$importPlugin = new ($importFormat->getClassName());
$importPlugin->setImportOptions($request);
// Do the real import
$defaultFkCheck = ForeignKey::handleDisableCheckInit();
try {
$queriesToBeExecuted = $importPlugin->doImport($importHandle ?? null);
ForeignKey::handleDisableCheckCleanup($defaultFkCheck);
} catch (Throwable $e) {
ForeignKey::handleDisableCheckCleanup($defaultFkCheck);
throw $e;
}
}
if (isset($importHandle)) {
$importHandle->close();
}
// Reset charset back, if we did some changes
if ($resetCharset) {
$this->dbi->query('SET CHARACTER SET ' . $this->dbi->getDefaultCharset());
$this->dbi->setCollation($this->dbi->getDefaultCollation());
}
// Show correct message
if ($idBookmark !== 0 && $actionBookmark === 2) {
$GLOBALS['message'] = Message::success(__('The bookmark has been deleted.'));
$GLOBALS['display_query'] = $GLOBALS['import_text'];
$GLOBALS['error'] = false; // unset error marker, it was used just to skip processing
} elseif ($idBookmark !== 0 && $actionBookmark === 1) {
$GLOBALS['message'] = Message::notice(__('Showing bookmark'));
} elseif (ImportSettings::$finished && ! $GLOBALS['error']) {
// Do not display the query with message, we do it separately
$GLOBALS['display_query'] = ';';
if (ImportSettings::$importType !== 'query') {
$GLOBALS['message'] = Message::success(
'<em>'
. _ngettext(
'Import has been successfully finished, %d query executed.',
'Import has been successfully finished, %d queries executed.',
ImportSettings::$executedQueries,
)
. '</em>',
);
$GLOBALS['message']->addParam(ImportSettings::$executedQueries);
if (ImportSettings::$importNotice !== '') {
$GLOBALS['message']->addHtml(ImportSettings::$importNotice);
}
if (ImportSettings::$localImportFile !== '') {
$GLOBALS['message']->addText('(' . ImportSettings::$localImportFile . ')');
} elseif (
isset($_FILES['import_file'])
&& is_array($_FILES['import_file'])
&& isset($_FILES['import_file']['name'])
&& is_string($_FILES['import_file']['name'])
) {
$GLOBALS['message']->addText('(' . $_FILES['import_file']['name'] . ')');
}
}
}
// Did we hit timeout? Tell it user.
if (ImportSettings::$timeoutPassed) {
$GLOBALS['urlParams']['timeout_passed'] = '1';
$GLOBALS['urlParams']['offset'] = ImportSettings::$offset;
if (ImportSettings::$localImportFile !== '') {
$GLOBALS['urlParams']['local_import_file'] = ImportSettings::$localImportFile;
}
$importUrl = $GLOBALS['errorUrl'] = $GLOBALS['goto'] . Url::getCommon($GLOBALS['urlParams'], '&');
$GLOBALS['message'] = Message::error(
__(
'Script timeout passed, if you want to finish import,'
. ' please %sresubmit the same file%s and import will resume.',
),
);
$GLOBALS['message']->addParamHtml('<a href="' . $importUrl . '">');
$GLOBALS['message']->addParamHtml('</a>');
if (ImportSettings::$offset === 0 || (isset($originalSkip) && $originalSkip == ImportSettings::$offset)) {
$GLOBALS['message']->addText(
__(
'However on last run no data has been parsed,'
. ' this usually means phpMyAdmin won\'t be able to'
. ' finish this import unless you increase php time limits.',
),
);
}
}
// if there is any message, copy it into $_SESSION as well,
// so we can obtain it by AJAX call
if (isset($GLOBALS['message'])) {
$_SESSION['Import_message']['message'] = $GLOBALS['message']->getDisplay();
}
// Parse and analyze the query, for correct db and table name
// in case of a query typed in the query window
// (but if the query is too large, in case of an imported file, the parser
// can choke on it so avoid parsing)
$sqlLength = mb_strlen($GLOBALS['sql_query']);
if ($sqlLength <= $config->settings['MaxCharactersInDisplayedSQL']) {
[$statementInfo, Current::$database, $tableFromSql] = ParseAnalyze::sqlQuery(
$GLOBALS['sql_query'],
Current::$database,
);
$GLOBALS['reload'] = $statementInfo->flags->reload;
ImportSettings::$offset = (int) $statementInfo->flags->offset;
if (Current::$table != $tableFromSql && $tableFromSql !== '') {
Current::$table = $tableFromSql;
}
}
foreach (ImportSettings::$failedQueries as $die) {
Generator::mysqlDie($die['error'], $die['sql'], false, $GLOBALS['errorUrl'], $GLOBALS['error']);
}
if (ImportSettings::$goSql) {
if ($queriesToBeExecuted === []) {
$queriesToBeExecuted = [$GLOBALS['sql_query']];
}
$htmlOutput = '';
foreach ($queriesToBeExecuted as $GLOBALS['sql_query']) {
// parse sql query
[$statementInfo, Current::$database, $tableFromSql] = ParseAnalyze::sqlQuery(
$GLOBALS['sql_query'],
Current::$database,
);
ImportSettings::$offset = (int) $statementInfo->flags->offset;
$GLOBALS['reload'] = $statementInfo->flags->reload;
// Check if User is allowed to issue a 'DROP DATABASE' Statement
if (
$this->sql->hasNoRightsToDropDatabase(
$statementInfo,
$config->settings['AllowUserDropDatabase'],
$this->dbi->isSuperUser(),
)
) {
Generator::mysqlDie(
__('"DROP DATABASE" statements are disabled.'),
'',
false,
$_SESSION['Import_message']['go_back_url'],
);
return $this->response->response();
}
if (Current::$table != $tableFromSql && $tableFromSql !== '') {
Current::$table = $tableFromSql;
}
$htmlOutput .= $this->sql->executeQueryAndGetQueryResponse(
$statementInfo,
false, // is_gotofile
Current::$database, // db
Current::$table, // table
null, // sql_query_for_bookmark - see below
null, // message_to_show
null, // sql_data
$GLOBALS['goto'], // goto
null, // disp_query
null, // disp_message
$GLOBALS['sql_query'], // sql_query
null, // complete_query
);
}
// sql_query_for_bookmark is not included in Sql::executeQueryAndGetQueryResponse
// since only one bookmark has to be added for all the queries submitted through
// the SQL tab
if (! empty($request->getParsedBodyParam('bkm_label')) && ! empty($GLOBALS['import_text'])) {
$relation = new Relation($this->dbi);
$this->sql->storeTheQueryAsBookmark(
$relation->getRelationParameters()->bookmarkFeature,
Current::$database,
$config->selectedServer['user'],
$request->getParsedBodyParam('sql_query'),
$request->getParsedBodyParam('bkm_label'),
$request->hasBodyParam('bkm_replace'),
);
}
$this->response->addJSON('ajax_reload', $GLOBALS['ajax_reload']);
$this->response->addHTML($htmlOutput);
return $this->response->response();
}
if ($request->hasBodyParam('rollback_query')) {
// We rollback because there might be other queries that need to be executed after this,
// e.g. creation of a bookmark.
$this->dbi->query('ROLLBACK');
ImportSettings::$message .= __('[ROLLBACK occurred.]');
}
if ($GLOBALS['result']) {
// Save a Bookmark with more than one queries (if Bookmark label given).
if (! empty($request->getParsedBodyParam('bkm_label')) && ! empty($GLOBALS['import_text'])) {
$relation = new Relation($this->dbi);
$this->sql->storeTheQueryAsBookmark(
$relation->getRelationParameters()->bookmarkFeature,
Current::$database,
$config->selectedServer['user'],
$request->getParsedBodyParam('sql_query'),
$request->getParsedBodyParam('bkm_label'),
$request->hasBodyParam('bkm_replace'),
);
}
$this->response->setRequestStatus(true);
$this->response->addJSON('message', Message::success(ImportSettings::$message));
$this->response->addJSON(
'sql_query',
Generator::getMessage(ImportSettings::$message, $GLOBALS['sql_query'], MessageType::Success),
);
} elseif ($GLOBALS['result'] === false) {
$this->response->setRequestStatus(false);
$this->response->addJSON('message', Message::error(ImportSettings::$message));
} else {
/** @psalm-suppress UnresolvableInclude */
include ROOT_PATH . $GLOBALS['goto'];
}
return $this->response->response();
}
}