setDescription('Dump the given database schema');
$this->addArgument('path', InputArgument::REQUIRED, 'path where the backup should be saved');
}
protected function execute(InputInterface $input, OutputInterface $output): int
{
$io = new SymfonyStyle($input, $output);
$dump_dir = realpath($input->getArgument('path'));
$today = date('Ymd');
$prefix = \Config::get()->STUDIP_INSTALLATION_ID ? \Config::get()->STUDIP_INSTALLATION_ID : 'studip';
if (!is_writeable($dump_dir)) {
$io->error('Directory: ' . $dump_dir . ' is not writeable!');
return Command::FAILURE;
}
$dump_db_dir = $dump_dir . '/db-' . $today;
if (!\is_dir($dump_db_dir)) {
\mkdir($dump_db_dir);
}
$command = $this->getBaseDumpCommand();
$output = [];
$result_code = 0;
foreach (\DBManager::get()->query('SHOW TABLES') as $tables) {
$table = $tables[0];
$dump_table = $dump_db_dir . '/' . $table . '-' . $today . '.sql';
$io->writeln('Dumping database table ' . $table . '');
$cmd = $command . ' ' . $table . ' > ' . $dump_table;
$this->runCommand($cmd, $output, $result_code);
if ($result_code > 0) {
$io->error($this->parseOutput($cmd, $output));
return Command::FAILURE;
}
}
$dump_db = $dump_dir . '/' . $prefix . '-DB-' . $today . '.tar.gz';
$io->writeln('Packing database to ' . $dump_db . '');
$cmd = "cd $dump_db_dir && tar -czf $dump_db *";
$this->runCommand($cmd, $output, $result_code);
if ($result_code > 0) {
$io->error($this->parseOutput($cmd, $output));
return Command::FAILURE;
}
$cmd = "rm -rf $dump_db_dir";
$this->runCommand($cmd, $output, $result_code);
if ($result_code > 0) {
$io->error($this->parseOutput($cmd, $output));
return Command::FAILURE;
}
return Command::SUCCESS;
}
/**
* Get the base dump command arguments for MySQL as a string.
*
* @return string
*/
private function getBaseDumpCommand(): string
{
$command =
'mysqldump ' .
$this->getConnectionString() .
' --skip-add-locks --skip-comments --skip-set-charset --tz-utc';
if (!\DBManager::get()->isMariaDB()) {
$command .= ' --column-statistics=0 --set-gtid-purged=OFF';
}
return $command . ' ' . $GLOBALS['DB_STUDIP_DATABASE'];
}
/**
* Generate a basic connection string (--socket, --host, --port, --user, --password) for the database.
*
* @return string
*/
private function getConnectionString(): string
{
return ' --user="' .
$GLOBALS['DB_STUDIP_USER'] .
'" --password="' .
$GLOBALS['DB_STUDIP_PASSWORD'] .
'" --host="' .
$GLOBALS['DB_STUDIP_HOST'] .
'"';
}
/**
* Execute dump command
* @param string $cmd
* @param array $output
* @param int $result_code
*/
private function runCommand(string $cmd, array &$output, int &$result_code)
{
exec($cmd . ' 2>&1', $output, $result_code);
}
/**
* Parse output of exec()
* @param string $cmd
* @param array $output
* @return string
*/
private function parseOutput(string &$cmd, array &$output): string
{
$result = join('\n', array_merge([$cmd], $output));
$cmd = '';
$output = [];
return $result;
}
}