120 lines
No EOL
3.6 KiB
PHP
120 lines
No EOL
3.6 KiB
PHP
<?php
|
|
|
|
namespace Cli\Services;
|
|
|
|
use Exception;
|
|
|
|
class MySqlRunner
|
|
{
|
|
public function __construct(
|
|
protected string $host,
|
|
protected string $user,
|
|
protected string $password,
|
|
protected string $database,
|
|
protected int $port = 3306
|
|
) {
|
|
}
|
|
|
|
/**
|
|
* @throws Exception
|
|
*/
|
|
public function ensureOptionsSet(): void
|
|
{
|
|
$options = ['host', 'user', 'password', 'database'];
|
|
foreach ($options as $option) {
|
|
if (!$this->$option) {
|
|
throw new Exception("Could not find a valid value for the \"{$option}\" database option.");
|
|
}
|
|
}
|
|
}
|
|
|
|
public function testConnection(): bool
|
|
{
|
|
$output = (new ProgramRunner('mysql', '/usr/bin/mysql'))
|
|
->withTimeout(240)
|
|
->withIdleTimeout(5)
|
|
->runCapturingStdErr([
|
|
'-h', $this->host,
|
|
'-P', $this->port,
|
|
'-u', $this->user,
|
|
'-p' . $this->password,
|
|
$this->database,
|
|
'-e' . "'show tables;'"
|
|
]);
|
|
|
|
return !$output;
|
|
}
|
|
|
|
public function importSqlFile(string $sqlFilePath): void
|
|
{
|
|
$output = (new ProgramRunner('mysql', '/usr/bin/mysql'))
|
|
->withTimeout(240)
|
|
->withIdleTimeout(5)
|
|
->runCapturingStdErr([
|
|
'-h', $this->host,
|
|
'-P', $this->port,
|
|
'-u', $this->user,
|
|
'-p' . $this->password,
|
|
$this->database,
|
|
'<', $sqlFilePath
|
|
]);
|
|
|
|
if ($output) {
|
|
throw new Exception("Failed mysql file import with errors:\n" . $output);
|
|
}
|
|
}
|
|
|
|
public function runDumpToFile(string $filePath): void
|
|
{
|
|
$file = fopen($filePath, 'w');
|
|
$errors = "";
|
|
$hasOutput = false;
|
|
|
|
try {
|
|
(new ProgramRunner('mysqldump', '/usr/bin/mysqldump'))
|
|
->withTimeout(240)
|
|
->withIdleTimeout(15)
|
|
->runWithoutOutputCallbacks([
|
|
'-h', $this->host,
|
|
'-P', $this->port,
|
|
'-u', $this->user,
|
|
'-p' . $this->password,
|
|
'--single-transaction',
|
|
'--no-tablespaces',
|
|
$this->database,
|
|
], function ($data) use (&$file, &$hasOutput) {
|
|
fwrite($file, $data);
|
|
$hasOutput = true;
|
|
}, function ($error) use (&$errors) {
|
|
$errors .= $error . "\n";
|
|
});
|
|
} catch (\Exception $exception) {
|
|
fclose($file);
|
|
if ($exception instanceof ProcessTimedOutException) {
|
|
if (!$hasOutput) {
|
|
throw new Exception("mysqldump operation timed-out.\nNo data has been received so the connection to your database may have failed.");
|
|
} else {
|
|
throw new Exception("mysqldump operation timed-out after data was received.");
|
|
}
|
|
}
|
|
throw new Exception($exception->getMessage());
|
|
}
|
|
|
|
fclose($file);
|
|
|
|
if ($errors) {
|
|
throw new Exception("Failed mysqldump with errors:\n" . $errors);
|
|
}
|
|
}
|
|
|
|
public static function fromEnvOptions(array $env): static
|
|
{
|
|
$host = ($env['DB_HOST'] ?? '');
|
|
$username = ($env['DB_USERNAME'] ?? '');
|
|
$password = ($env['DB_PASSWORD'] ?? '');
|
|
$database = ($env['DB_DATABASE'] ?? '');
|
|
$port = intval($env['DB_PORT'] ?? 3306);
|
|
|
|
return new static($host, $username, $password, $database, $port);
|
|
}
|
|
} |