Backup::restore()   A
last analyzed

Complexity

Conditions 5
Paths 5

Size

Total Lines 28

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 28
rs 9.1608
c 0
b 0
f 0
cc 5
nc 5
nop 1
1
<?php
2
3
namespace Cornford\Backup;
4
5
use Cornford\Backup\Exceptions\BackupException;
6
use Cornford\Backup\Exceptions\BackupExportException;
7
use Cornford\Backup\Exceptions\BackupRestoreException;
8
use DirectoryIterator;
9
use Exception;
10
11
class Backup extends BackupAbstract
12
{
13
    /**
14
     * Export database to file.
15
     *
16
     * @param string $filename
17
     *
18
     * @throws BackupExportException|BackupException
19
     *
20
     * @return bool
21
     */
22
    public function export($filename = null): bool
23
    {
24
        if (!$this->getEnabled()) {
25
            return false;
26
        }
27
28
        if ($filename === null) {
29
            $filename = $this->getFilename();
30
        }
31
32
        $path = $this->getPath();
33
34
        if (!$this->getBackupFilesystemInstance()->checkPathExists($path)) {
35
            throw new BackupExportException('Unable to export to path "' . $path . '" as it doesn\'t exist.');
36
        }
37
38
        $filepath = $path . '/' . $filename . '.' . $this->getBackupEngineInstance()->getFileExtension();
39
40
        $this->setWorkingFilepath($filepath);
41
        $result = $this->getBackupEngineInstance()->export($filepath);
42
43
        if ($result) {
44
            if ($this->getCompress()) {
45
                $filepath = $this->compressFile($filepath);
46
            }
47
48
            $this->setWorkingFilepath($filepath);
49
        } else {
50
            $this->removeTemporaryFiles($filepath, true);
51
            $this->setWorkingFilepath(null);
52
        }
53
54
        return $result;
55
    }
56
57
    /**
58
     * Restore database from file path.
59
     *
60
     * @param string $filepath
61
     *
62
     * @throws BackupRestoreException
63
     *
64
     * @return bool
65
     */
66
    public function restore($filepath): bool
67
    {
68
        if (!$this->getEnabled()) {
69
            return false;
70
        }
71
72
        if (!$this->getBackupFilesystemInstance()->checkFileExists($filepath)) {
73
            throw new BackupRestoreException('Unable to restore file "' . $filepath . '" as it doesn\'t exist.');
74
        }
75
76
        $this->setWorkingFilepath($filepath);
77
78
        if ($this->getBackupFilesystemInstance()->checkFileEmpty($filepath)) {
79
            $this->getBackupFilesystemInstance()->removeFile($filepath);
80
81
            return false;
82
        }
83
84
        if ($this->isCompressed($filepath)) {
85
            $filepath = $this->decompressFile($filepath);
86
        }
87
88
        $result = $this->getBackupEngineInstance()->restore($filepath);
89
90
        $this->removeTemporaryFiles($this->getWorkingFilepath());
91
92
        return $result;
93
    }
94
95
    /**
96
     * Is a file compressed?
97
     *
98
     * @param string $filepath
99
     *
100
     * @return bool
101
     */
102
    protected function isCompressed($filepath): bool
103
    {
104
        return (pathinfo($filepath, PATHINFO_EXTENSION) === 'gz');
105
    }
106
107
    /**
108
     * Remove temporary files.
109
     *
110
     * @param string $filepath
111
     * @param bool   $force
112
     *
113
     * @return void
114
     */
115
    protected function removeTemporaryFiles($filepath, $force = false): void
116
    {
117
        if ($force || $filepath !== $this->getUncompressedFilepath($filepath)) {
118
            $this->getBackupFilesystemInstance()->removeFile($this->getUncompressedFilepath($filepath));
119
        }
120
    }
121
122
    /**
123
     * Compress a file with gzip.
124
     *
125
     * @param string $filepath
126
     *
127
     * @throws BackupException
128
     *
129
     * @return string
130
     */
131
    protected function compressFile($filepath): string
132
    {
133
        if (!$this->getBackupFilesystemInstance()->checkFunctionExists('gzencode')) {
134
            throw new BackupException('The method: "gzencode" isn\'t currently enabled.');
135
        }
136
137
        $compressedFilepath = $this->getCompressedFilepath($filepath);
138
        $this->getBackupFilesystemInstance()->writeCompressedFile($compressedFilepath, $filepath);
139
        $this->getBackupFilesystemInstance()->removeFile($filepath);
140
141
        return $compressedFilepath;
142
    }
143
144
    /**
145
     * Decompress a file with gzip.
146
     *
147
     * @param string $filepath
148
     *
149
     * @throws BackupException
150
     *
151
     * @return string
152
     */
153
    protected function decompressFile($filepath): string
154
    {
155
        if (!$this->getBackupFilesystemInstance()->checkFunctionExists('gzdecode')) {
156
            throw new BackupException('The method: "gzdecode" isn\'t currently enabled.');
157
        }
158
159
        $uncompressedFilepath = $this->getUncompressedFilepath($filepath);
160
        $this->getBackupFilesystemInstance()->writeUncompressedFile($uncompressedFilepath, $filepath);
161
162
        return $uncompressedFilepath;
163
    }
164
165
    /**
166
     * Get an compressed filepath from a uncompressed filepath.
167
     *
168
     * @param string $filepath
169
     *
170
     * @return string
171
     */
172
    protected function getCompressedFilepath($filepath): string
173
    {
174
        return $filepath . '.gz';
175
    }
176
177
    /**
178
     * Get an uncompressed filepath from a compressed filepath.
179
     *
180
     * @param string $filepath
181
     *
182
     * @return string
183
     */
184
    protected function getUncompressedFilepath($filepath): string
185
    {
186
        return preg_replace('|\.gz$|', '', $filepath);
187
    }
188
189
    /**
190
     * Get database restoration files.
191
     *
192
     * @param string $path
193
     *
194
     * @throws BackupException
195
     *
196
     * @return array
197
     */
198
    public function getRestorationFiles($path = null): array
199
    {
200
        if ($path === null) {
201
            $path = $this->getPath();
202
        }
203
204
        $results = [];
205
206
        if (!$this->getBackupFilesystemInstance()->checkPathExists($path)) {
207
            throw new BackupException('Unable to get restoration files as path "' . $path . '" doesn\'t exist');
208
        }
209
210
        try {
211
            foreach (new DirectoryIterator($path) as $fileinfo) {
212
                if (
213
                    $fileinfo->isDot()
214
                    || !$fileinfo->isFile()
215
                    || in_array($fileinfo->getFilename(), BackupFilesystem::$ignoredFiles)
216
                    || substr($fileinfo->getFilename(), 0, 1) == '.'
217
                ) {
218
                    continue;
219
                }
220
221
                $results[$fileinfo->getMTime()] = $fileinfo->getPathname();
222
            }
223
        } catch (Exception $exception) {
224
            // Exception thrown continue and return empty result set
225
        }
226
227
        ksort($results);
228
229
        return $results;
230
    }
231
232
    /**
233
     * Get database process output.
234
     *
235
     * @return string
236
     */
237
    public function getProcessOutput(): string
238
    {
239
        return self::$backupEngineInstance->getProcessOutput();
240
    }
241
}
242