1 <?php declare(strict_types=1);
3 namespace Tests\Commands;
8 class RestoreCommandTest extends TestCase
11 public function test_restore_into_cwd_by_default_with_all_content_types()
13 $mysql = new mysqli('db', 'bookstack', 'bookstack', 'bookstack');
14 $mysql->query('CREATE TABLE xx_testing (labels varchar(255));');
16 $result = $mysql->query('SHOW TABLES LIKE \'zz_testing\';');
17 $this->assertEquals(0, mysqli_num_rows($result));
19 $zipFile = $this->buildZip(function (\ZipArchive $zip) {
20 $zip->addFromString('.env', "APP_KEY=abc123\nAPP_URL=https://example.com");
21 $zip->addFromString('public/uploads/test.txt', 'hello-public-uploads');
22 $zip->addFromString('storage/uploads/test.txt', 'hello-storage-uploads');
23 $zip->addFromString('themes/test.txt', 'hello-themes');
24 $zip->addFromString('db.sql', "CREATE TABLE zz_testing (names varchar(255));\nINSERT INTO zz_testing values ('barry');");
27 exec('cp -r /var/www/bookstack /var/www/bookstack-restore');
28 chdir('/var/www/bookstack-restore');
30 $result = $this->runCommand('restore', [
31 'backup-zip' => $zipFile,
34 $result->assertSuccessfulExit();
35 $result->assertStdoutContains('✔ .env Config File');
36 $result->assertStdoutContains('✔ Themes Folder');
37 $result->assertStdoutContains('✔ Public File Uploads');
38 $result->assertStdoutContains('✔ Private File Uploads');
39 $result->assertStdoutContains('✔ Database Dump');
40 $result->assertStdoutContains('Restore operation complete!');
42 $result = $mysql->query('SELECT * FROM zz_testing where names = \'barry\';');
43 $this->assertEquals(1, mysqli_num_rows($result));
44 $result = $mysql->query('SHOW TABLES LIKE \'xx_testing\';');
45 $this->assertEquals(0, mysqli_num_rows($result));
47 $this->assertStringEqualsFile('/var/www/bookstack-restore/public/uploads/test.txt', 'hello-public-uploads');
48 $this->assertStringEqualsFile('/var/www/bookstack-restore/storage/uploads/test.txt', 'hello-storage-uploads');
49 $this->assertStringEqualsFile('/var/www/bookstack-restore/themes/test.txt', 'hello-themes');
50 $env = file_get_contents('/var/www/bookstack-restore/.env');
51 $this->assertStringContainsString('APP_KEY=abc123', $env);
52 $this->assertStringContainsString('APP_URL=https://example.com', $env);
54 $mysql->query("DROP TABLE zz_testing;");
55 exec('rm -rf /var/www/bookstack-restore');
58 public function test_command_fails_on_zip_with_no_expected_contents()
60 $zipFile = $this->buildZip(function (\ZipArchive $zip) {
61 $zip->addFromString('spaghetti', "Hello world!");
64 chdir('/var/www/bookstack');
66 $result = $this->runCommand('restore', [
67 'backup-zip' => $zipFile,
70 $result->assertErrorExit();
71 $result->assertStderrContains("Provided ZIP backup [{$zipFile}] does not have any expected restorable content.");
74 public function test_limited_restore_using_app_directory_option()
76 $zipFile = $this->buildZip(function (\ZipArchive $zip) {
77 $zip->addFromString('db.sql', "CREATE TABLE zz_testing (names varchar(255));");
78 $zip->addFromString('themes/hello.txt', "limited restore test!");
83 $result = $this->runCommand('restore', [
84 'backup-zip' => $zipFile,
85 '--app-directory' => '/var/www/bookstack'
88 $result->assertSuccessfulExit();
89 $result->assertStdoutContains('❌ .env Config File');
90 $result->assertStdoutContains('✔ Themes Folder');
91 $result->assertStdoutContains('❌ Public File Uploads');
92 $result->assertStdoutContains('❌ Private File Uploads');
93 $result->assertStdoutContains('✔ Database Dump');
94 $this->assertStringEqualsFile('/var/www/bookstack/themes/hello.txt', 'limited restore test!');
96 unlink('/var/www/bookstack/themes/hello.txt');
97 $mysql = new mysqli('db', 'bookstack', 'bookstack', 'bookstack');
98 $mysql->query("DROP TABLE zz_testing;");
101 public function test_restore_with_symlinked_content_folders()
103 $zipFile = $this->buildZip(function (\ZipArchive $zip) {
104 $zip->addFromString('.env', "APP_KEY=abc123\nAPP_URL=https://example.com");
105 $zip->addFromString('public/uploads/test.txt', 'hello-public-uploads');
106 $zip->addFromString('storage/uploads/test.txt', 'hello-storage-uploads');
107 $zip->addFromString('themes/test.txt', 'hello-themes');
110 exec('cp -r /var/www/bookstack /var/www/bookstack-symlink-restore');
111 chdir('/var/www/bookstack-symlink-restore');
114 $symlinkPaths = ['public/uploads', 'storage/uploads', '.env', 'themes'];
115 foreach ($symlinkPaths as $path) {
116 $targetFile = str_replace('/', '-', $path);
119 exec("mv /var/www/bookstack-symlink-restore/{$path} /symlinks/{$targetFile}", $output, $code);
120 exec("ln -s /symlinks/{$targetFile} /var/www/bookstack-symlink-restore/{$path}", $output, $code);
122 $this->fail("Error when setting up symlinks");
126 $result = $this->runCommand('restore', [
127 'backup-zip' => $zipFile,
130 $result->assertSuccessfulExit();
132 $this->assertStringEqualsFile('/var/www/bookstack-symlink-restore/public/uploads/test.txt', 'hello-public-uploads');
133 $this->assertStringEqualsFile('/var/www/bookstack-symlink-restore/storage/uploads/test.txt', 'hello-storage-uploads');
134 $this->assertStringEqualsFile('/var/www/bookstack-symlink-restore/themes/test.txt', 'hello-themes');
136 exec('rm -rf /var/www/bookstack-symlink-restore');
139 protected function buildZip(callable $builder): string
141 $zipFile = tempnam(sys_get_temp_dir(), 'cli-test');
142 $testZip = new \ZipArchive('');
143 $testZip->open($zipFile);