Skip to content

Commit

Permalink
Merge pull request #81 from mirko-pagliai/develop
Browse files Browse the repository at this point in the history
Develop
  • Loading branch information
mirko-pagliai authored Nov 25, 2021
2 parents cfe9dea + d0a2fc9 commit c6a9b92
Show file tree
Hide file tree
Showing 27 changed files with 258 additions and 504 deletions.
12 changes: 12 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,16 @@
# 2.x branch
## 2.10 branch
### 2.10.0-beta1
* now allows to configure and customize via bootstrap the executable commands to
import and export databases, for each driver, with placeholders;
* `__exportExecutableWithCompression()` and `_importExecutableWithCompression()`
methods provided by the `Driver` class have been removed and incorporated
into the new `_getExportExecutable()` and `_getImportExecutable()`;
* `BackupTrait::$validExtensions` has been removed and replaced by the
`DATABASE_BACKUP_EXTENSIONS` constant;
* postgres and sqlite commands are also properly escaped;
* many little fixes and many code simplifications.

## 2.9 branch
### 2.9.2
* added `BackupTrait::getDriverName()` static method; `getConnection()` and
Expand Down
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@
],
"cs-check": "phpcs --standard=phpcs.xml.dist",
"cs-fix": "phpcbf --standard=phpcs.xml.dist",
"test": "rm -f -r /tmp/cake* && phpunit",
"test": "rm -f -r /tmp/cake* && phpunit && driver_test=sqlite phpunit && driver_test=postgres phpunit",
"coverage": "XDEBUG_MODE=coverage phpunit --coverage-html=coverage",
"phpstan": "phpstan.phar analyse",
"psalm": "psalm.phar",
Expand Down
37 changes: 35 additions & 2 deletions config/bootstrap.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,32 @@
use Cake\Core\Configure;
use Tools\Filesystem;

/**
* Executables. Name of driver as keys, Then, as value, an array that contains
* first the executable to export and then the executable to import backups.
*/
if (!defined('DATABASE_BACKUP_EXECUTABLES')) {
define('DATABASE_BACKUP_EXECUTABLES', [
'mysql' => ['export' => 'mysqldump', 'import' => 'mysql'],
'postgres' => ['export' => 'pg_dump', 'import' => 'pg_restore'],
'sqlite' => ['export' => 'sqlite3', 'import' => 'sqlite3'],
]);
}

/**
* Valid extensions. Names as keys and compressions as values
*/
if (!defined('DATABASE_BACKUP_EXTENSIONS')) {
define('DATABASE_BACKUP_EXTENSIONS', ['sql.bz2' => 'bzip2', 'sql.gz' => 'gzip', 'sql' => false]);
}

//Database connection
if (!Configure::check('DatabaseBackup.connection')) {
Configure::write('DatabaseBackup.connection', 'default');
}

//Auto-discovers binaries
foreach (['mysql', 'mysqldump', 'pg_dump', 'pg_restore','sqlite3', 'bzip2', 'gzip'] as $binary) {
foreach (array_unique(array_merge(array_column(DATABASE_BACKUP_EXECUTABLES, 'export'), array_column(DATABASE_BACKUP_EXECUTABLES, 'import'), ['bzip2', 'gzip'])) as $binary) {
if (!Configure::check('DatabaseBackup.binaries.' . $binary)) {
try {
$binaryPath = which($binary);
Expand All @@ -38,13 +57,27 @@
Configure::write('DatabaseBackup.chmod', 0664);
}

//Default executable commands to export/import databases
foreach ([
'DatabaseBackup.mysql.export' => '{{BINARY}} --defaults-file={{AUTH_FILE}} {{DB_NAME}}',
'DatabaseBackup.mysql.import' => '{{BINARY}} --defaults-extra-file={{AUTH_FILE}} {{DB_NAME}}',
'DatabaseBackup.postgres.export' => '{{BINARY}} --format=c -b --dbname=\'postgresql://{{DB_USER}}{{DB_PASSWORD}}@{{DB_HOST}}/{{DB_NAME}}\'',
'DatabaseBackup.postgres.import' => '{{BINARY}} --format=c -c -e --dbname=\'postgresql://{{DB_USER}}{{DB_PASSWORD}}@{{DB_HOST}}/{{DB_NAME}}\'',
'DatabaseBackup.sqlite.export' => '{{BINARY}} {{DB_NAME}} .dump',
'DatabaseBackup.sqlite.import' => '{{BINARY}} {{DB_NAME}}',
] as $k => $v) {
if (!Configure::check($k)) {
Configure::write($k, $v);
}
}

//Default target directory
if (!Configure::check('DatabaseBackup.target')) {
Configure::write('DatabaseBackup.target', Filesystem::instance()->concatenate(ROOT, 'backups'));
}

//Checks for the target directory
$target = Configure::read('DatabaseBackup.target');
$target = Configure::readOrFail('DatabaseBackup.target');
if (!file_exists($target)) {
mkdir($target, 0777);
}
Expand Down
6 changes: 3 additions & 3 deletions phpstan-baseline.neon
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ parameters:
path: tests/TestCase/Driver/DriverTest.php

-
message: "#^Negated boolean expression is always false\\.$#"
count: 1
path: tests/TestCase/Utility/BackupExportTest.php
message: "#^Ternary operator condition is always true\\.$#"
count: 2
path: tests/TestCase/Utility/BackupImportTest.php

6 changes: 6 additions & 0 deletions psalm.xml
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,12 @@
</errorLevel>
</InvalidDocblock>

<InvalidReturnType>
<errorLevel type="suppress">
<file name="src/BackupTrait.php" />
</errorLevel>
</InvalidReturnType>

<RedundantCondition>
<errorLevel type="suppress">
<file name="src/Driver/Mysql.php" />
Expand Down
48 changes: 19 additions & 29 deletions src/BackupTrait.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,50 +28,43 @@
*/
trait BackupTrait
{
/**
* Valid extensions. Names as keys and compressions as values
* @since 2.4.0
* @var array<string, string|bool>
*/
protected static $validExtensions = ['sql.bz2' => 'bzip2', 'sql.gz' => 'gzip', 'sql' => false];

/**
* Returns the absolute path for a backup file
* @param string $path Relative or absolute path
* @return string
*/
public static function getAbsolutePath(string $path): string
{
return Filesystem::instance()->makePathAbsolute($path, Configure::read('DatabaseBackup.target'));
return Filesystem::instance()->makePathAbsolute($path, Configure::readOrFail('DatabaseBackup.target'));
}

/**
* Returns the compression type from a filename
* @param string $filename Filename
* Returns the compression type for a backup file
* @param string $path File path
* @return string|null Compression type or `null`
*/
public static function getCompression(string $filename): ?string
public static function getCompression(string $path): ?string
{
$extension = self::getExtension($filename);
$extension = self::getExtension($path);

return self::getValidCompressions()[$extension] ?? null;
}

/**
* Gets the connection array
* Gets the `Connection` instance
* @param string|null $name Connection name
* @return \Cake\Datasource\ConnectionInterface A connection object
* @return \Cake\Datasource\ConnectionInterface A `Connection` object
*/
public static function getConnection(?string $name = null): ConnectionInterface
{
return ConnectionManager::get($name ?: Configure::readOrFail('DatabaseBackup.connection'));
}

/**
* Gets the driver instance containing all methods to export/import database
* Gets the `Driver` instance containing all methods to export/import database
* backups, according to the connection
* @param \Cake\Datasource\ConnectionInterface|null $connection A connection object
* @return \DatabaseBackup\Driver\Driver A driver instance
* @param \Cake\Datasource\ConnectionInterface|null $connection A `Connection` object
* @return \DatabaseBackup\Driver\Driver A `Driver` instance
* @since 2.0.0
* @throws \InvalidArgumentException
*/
Expand All @@ -87,7 +80,7 @@ public static function getDriver(?ConnectionInterface $connection = null): Drive

/**
* Gets the driver name, according to the connection
* @param \Cake\Datasource\ConnectionInterface|null $connection A connection object
* @param \Cake\Datasource\ConnectionInterface|null $connection A `Connection` object
* @return string Driver name
* @since 2.9.2
*/
Expand All @@ -99,27 +92,24 @@ public static function getDriverName(?ConnectionInterface $connection = null): s
}

/**
* Returns the extension from a filename
* @param string $filename Filename
* @return string|null Extension or `null` if the extension is not found or
* if is an invalid extension
* @uses $validExtensions
* Returns the extension for a backup file
* @param string $path File path
* @return string|null Extension or `null` for invalid extensions
*/
public static function getExtension(string $filename): ?string
public static function getExtension(string $path): ?string
{
$extension = Filesystem::instance()->getExtension($filename);
$extension = Filesystem::instance()->getExtension($path);

return in_array($extension, array_keys(self::$validExtensions)) ? $extension : null;
return in_array($extension, array_keys(DATABASE_BACKUP_EXTENSIONS)) ? $extension : null;
}

/**
* Returns all valid compressions
* @return array
* @return array<string, string>
* @since 2.4.0
* @uses $validExtensions
*/
public static function getValidCompressions(): array
{
return array_filter(self::$validExtensions);
return array_filter(DATABASE_BACKUP_EXTENSIONS);
}
}
2 changes: 1 addition & 1 deletion src/Command/RotateCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ public function execute(Arguments $args, ConsoleIo $io): void

try {
//Gets deleted files
$files = (new BackupManager())->rotate((int)$args->getArgument('keep'));
$files = BackupManager::rotate((int)$args->getArgument('keep'));

if (!$files) {
$io->verbose(__d('database_backup', 'No backup has been deleted'));
Expand Down
2 changes: 1 addition & 1 deletion src/Command/SendCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@ public function execute(Arguments $args, ConsoleIo $io): void
parent::execute($args, $io);

try {
(new BackupManager())->send($args->getArgument('filename') ?: '', $args->getArgument('recipient') ?: '');
BackupManager::send($args->getArgument('filename') ?: '', $args->getArgument('recipient') ?: '');
$io->success(__d('database_backup', 'Backup `{0}` was sent via mail', Filesystem::instance()->rtr($args->getArgument('filename') ?: '')));
} catch (Exception $e) {
$io->error($e->getMessage());
Expand Down
6 changes: 2 additions & 4 deletions src/Console/Command.php
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,8 @@ class Command extends BaseCommand
*/
public function execute(Arguments $args, ConsoleIo $io): void
{
$config = $this->getConnection()->config();

$io->out(__d('database_backup', 'Connection: {0}', $config['name']));
$io->out(__d('database_backup', 'Driver: {0}', get_class_short_name($this->getConnection()->getDriver())));
$io->out(__d('database_backup', 'Connection: {0}', $this->getConnection()->config()['name']));
$io->out(__d('database_backup', 'Driver: {0}', $this->getDriverName()));
$io->hr();
}
}
Loading

0 comments on commit c6a9b92

Please sign in to comment.