Skip to content

Commit ae91014

Browse files
committed
initial commit
1 parent ab9f24a commit ae91014

11 files changed

+357
-0
lines changed

.editorconfig

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
root = true
2+
3+
[*]
4+
end_of_line = lf
5+
charset = utf-8
6+
trim_trailing_whitespace = true
7+
insert_final_newline = true
8+
indent_style = space
9+
indent_size = 2
10+
11+
[*.{diff,md}]
12+
trim_trailing_whitespace = false
13+
14+
[*.{php,xml,json}]
15+
indent_size = 4

.gitattributes

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
**/.gitattributes export-ignore
2+
**/.gitignore export-ignore
3+
**/.gitmodules export-ignore
4+
**/.github export-ignore
5+
**/.travis export-ignore
6+
**/.travis.yml export-ignore
7+
**/.editorconfig export-ignore
8+
**/.styleci.yml export-ignore
9+
10+
**/phpunit.xml export-ignore
11+
**/tests export-ignore
12+
13+
**/js/dist/**/* -diff
14+
**/js/dist/**/* linguist-generated
15+
**/js/dist-typings/**/* -diff
16+
**/js/dist-typings/**/* linguist-generated
17+
**/js/yarn.lock -diff
18+
**/js/package-lock.json -diff
19+
20+
* text=auto eol=lf

.github/FUNDING.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
github: [android-com-pl, rafaucau]

.github/workflows/backend.yml

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
name: Flarum DB Dumper PHP
2+
3+
on: [workflow_dispatch, push, pull_request]
4+
5+
jobs:
6+
run:
7+
uses: flarum/framework/.github/workflows/[email protected]
8+
with:
9+
enable_backend_testing: false
10+
enable_phpstan: false
11+
php_versions: '["8.1", "8.2", "8.3", "8.4"]'
12+
13+
backend_directory: .

.gitignore

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
.idea
2+
.vscode
3+
.fleet
4+
5+
/vendor
6+
composer.lock

.styleci.yml

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
preset: recommended
2+
3+
enabled:
4+
- logical_not_operators_with_successor_space
5+
6+
disabled:
7+
- align_double_arrow
8+
- blank_line_after_opening_tag
9+
- multiline_array_trailing_comma
10+
- new_with_braces
11+
- phpdoc_align
12+
- phpdoc_order
13+
- phpdoc_separation
14+
- phpdoc_types

README.md

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
# Flarum DB Dumper
2+
3+
Database backup extension for Flarum that allows dumping database content using the `db:dump` command.
4+
5+
## Installation
6+
7+
```sh
8+
composer require acpl/flarum-db-dumper
9+
```
10+
11+
## Usage
12+
13+
Basic usage:
14+
```sh
15+
# Dump to storage/dumps/dump-YYYY-MM-DD-HHMMSS.sql
16+
php flarum db:dump
17+
18+
# Dump to specific path/file
19+
php flarum db:dump /path/to/backup.sql
20+
php flarum db:dump ../backups/forum.sql
21+
22+
# Dump with compression (based on extension)
23+
php flarum db:dump /backups/dump.sql.gz # gzip compression
24+
php flarum db:dump /backups/dump.sql.bz2 # bzip2 compression
25+
```
26+
27+
### Options
28+
29+
- `--compress`: Use compression (`gz` or `bz2`), e.g. `--compress=gz` for gzip
30+
- `--include-tables=table1,table2`: Include only specific tables
31+
- `--exclude-tables=table1,table2`: Exclude specific tables
32+
- `--skip-structure`: Skip table structure
33+
- `--no-data`: Skip table data, dump only structure
34+
- `--skip-auto-increment`: Skip AUTO_INCREMENT values
35+
- `--no-column-statistics`: Disable column statistics (for MySQL 8 compatibility)
36+
- `--binary-path=/path/to/binary`: Custom mysqldump binary location
37+
38+
## Requirements
39+
40+
- `mysqldump` binary
41+
- `gzip` for `.gz` compression
42+
- `bzip2` for `.bz2` compression
43+
44+
## Links
45+
46+
- [Packagist](https://packagist.org/packages/acpl/flarum-db-dumper)
47+
- [GitHub](https://github.com/android-com-pl/flarum-db-dumper)

composer.json

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
{
2+
"name": "acpl/flarum-db-dumper",
3+
"description": "Dump the contents of a Flarum database",
4+
"type": "flarum-extension",
5+
"homepage": "https://github.com/android-com-pl/flarum-db-dumper",
6+
"license": "MIT",
7+
"authors": [
8+
{
9+
"name": "Rafał Całka",
10+
"homepage": "https://github.com/rafaucau",
11+
"role": "Developer"
12+
}
13+
],
14+
"require": {
15+
"php": ">=8.1",
16+
"flarum/core": "^1.8",
17+
"spatie/db-dumper": "^3.7"
18+
},
19+
"autoload": {
20+
"psr-4": {
21+
"ACPL\\FlarumDbDumper\\": "src/"
22+
}
23+
},
24+
"extra": {
25+
"flarum-extension": {
26+
"title": "DB Dumper",
27+
"category": "feature",
28+
"icon": {
29+
"name": "fas fa-database",
30+
"backgroundColor": "#0F9D58",
31+
"color": "#fff"
32+
}
33+
},
34+
"flarum-cli": {
35+
"modules": {
36+
"admin": false,
37+
"forum": false,
38+
"js": false,
39+
"jsCommon": false,
40+
"gitConf": true,
41+
"githubActions": true,
42+
"prettier": false,
43+
"typescript": false,
44+
"bundlewatch": false,
45+
"backendTesting": false,
46+
"editorConfig": true,
47+
"styleci": true,
48+
"css": false
49+
}
50+
}
51+
},
52+
"minimum-stability": "dev",
53+
"prefer-stable": true,
54+
"config": {
55+
"sort-packages": true
56+
}
57+
}

extend.php

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
<?php
2+
3+
namespace ACPL\FlarumDbDumper;
4+
5+
use Flarum\Extend;
6+
7+
return [
8+
(new Extend\Console())->command(DumbDbCommand::class),
9+
];

phpstan.neon

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
includes:
2+
- vendor/flarum/phpstan/extension.neon
3+
4+
parameters:
5+
level: 5
6+
paths:
7+
- src
8+
- extend.php
9+
excludePaths:
10+
- *.blade.php
11+
checkMissingIterableValueType: false
12+
databaseMigrationsPath: ['migrations']

src/DumbDbCommand.php

Lines changed: 163 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,163 @@
1+
<?php
2+
3+
namespace ACPL\FlarumDbDumper;
4+
5+
use Carbon\Carbon;
6+
use Exception;
7+
use Flarum\Console\AbstractCommand;
8+
use Flarum\Foundation\{Config, Paths};
9+
use Spatie\DbDumper\Databases\MySql;
10+
use Spatie\DbDumper\Compressors\{GzipCompressor, Bzip2Compressor};
11+
use Spatie\DbDumper\Exceptions\CannotSetParameter;
12+
use Symfony\Component\Console\Input\{InputArgument, InputOption};
13+
14+
class DumbDbCommand extends AbstractCommand
15+
{
16+
private const COMPRESSORS = [
17+
'gz' => GzipCompressor::class,
18+
'bz2' => Bzip2Compressor::class,
19+
];
20+
21+
public function __construct(protected Config $config, protected Paths $paths)
22+
{
23+
parent::__construct();
24+
}
25+
26+
protected function configure(): void
27+
{
28+
$this
29+
->setName('db:dump')
30+
->setDescription('Dump the contents of a database')
31+
->addArgument(
32+
'path',
33+
InputArgument::OPTIONAL,
34+
'Path where to store the dump file',
35+
)
36+
->addOption(
37+
'compress',
38+
null,
39+
InputOption::VALUE_REQUIRED,
40+
'Compression type (gz, bz2)',
41+
)
42+
->addOption(
43+
'binary-path',
44+
null,
45+
InputOption::VALUE_REQUIRED,
46+
'Custom location for the mysqldump binary',
47+
)
48+
->addOption(
49+
'include-tables',
50+
null,
51+
InputOption::VALUE_REQUIRED,
52+
'Comma separated list of tables to include in the dump',
53+
)
54+
->addOption(
55+
'exclude-tables',
56+
null,
57+
InputOption::VALUE_REQUIRED,
58+
'Comma separated list of tables to exclude from the dump',
59+
)
60+
->addOption(
61+
'skip-structure',
62+
null,
63+
InputOption::VALUE_NONE,
64+
'Skip table structure (CREATE TABLE statements)',
65+
)
66+
->addOption(
67+
'no-data',
68+
null,
69+
InputOption::VALUE_NONE,
70+
'Do not write row data',
71+
)
72+
->addOption(
73+
'skip-auto-increment',
74+
null,
75+
InputOption::VALUE_NONE,
76+
'Skip AUTO_INCREMENT values from the dump',
77+
)
78+
->addOption(
79+
'no-column-statistics',
80+
null,
81+
InputOption::VALUE_NONE,
82+
'Do not use column statistics (for MySQL 8 compatibility with older versions)',
83+
);
84+
}
85+
86+
/**
87+
* @throws CannotSetParameter
88+
*/
89+
protected function fire(): int
90+
{
91+
$dbConfig = $this->config['database'];
92+
$dumper = MySql::create()
93+
->setHost($dbConfig['host'])
94+
->setDbName($dbConfig['database'])
95+
->setPort($dbConfig['port'] ?? 3306)
96+
->setUserName($dbConfig['username'])
97+
->setPassword($dbConfig['password']);
98+
99+
$path = $this->input->getArgument('path');
100+
if (empty($path)) {
101+
$path = $this->paths->storage.'/dumps/dump-'.Carbon::now()->format('Y-m-d-His').'.sql';
102+
}
103+
104+
$compression = $this->input->getOption('compress');
105+
$extension = pathinfo($path, PATHINFO_EXTENSION);
106+
// If compression is specified and different from path extension
107+
if ($compression && $extension !== $compression) {
108+
$path .= '.'.$compression;
109+
} elseif (! $extension) {
110+
$path .= '.sql';
111+
}
112+
113+
$finalExtension = pathinfo($path, PATHINFO_EXTENSION);
114+
if (isset(self::COMPRESSORS[$finalExtension])) {
115+
$compressorClass = self::COMPRESSORS[$finalExtension];
116+
$dumper->useCompressor(new $compressorClass());
117+
}
118+
119+
$dir = dirname($path);
120+
if (! file_exists($dir)) {
121+
mkdir($dir, 0755, true);
122+
}
123+
124+
125+
if ($binaryPath = $this->input->getOption('binary-path')) {
126+
$dumper->setDumpBinaryPath($binaryPath);
127+
}
128+
129+
if ($includeTables = $this->input->getOption('include-tables')) {
130+
$dumper->includeTables(explode(',', $includeTables));
131+
}
132+
133+
if ($excludeTables = $this->input->getOption('exclude-tables')) {
134+
$dumper->excludeTables(explode(',', $excludeTables));
135+
}
136+
137+
if ($this->input->getOption('skip-structure')) {
138+
$dumper->doNotCreateTables();
139+
}
140+
141+
if ($this->input->getOption('no-data')) {
142+
$dumper->doNotDumpData();
143+
}
144+
145+
if ($this->input->getOption('skip-auto-increment')) {
146+
$dumper->skipAutoIncrement();
147+
}
148+
149+
if ($this->input->getOption('no-column-statistics')) {
150+
$dumper->doNotUseColumnStatistics();
151+
}
152+
153+
try {
154+
$dumper->dumpToFile($path);
155+
$this->info("Database dumped successfully to: $path");
156+
} catch (Exception $e) {
157+
$this->error('Failed to dump database: '.$e->getMessage());
158+
return 1;
159+
}
160+
161+
return 0;
162+
}
163+
}

0 commit comments

Comments
 (0)