1 | <?php |
||
30 | class StreamDestination implements DestinationInterface |
||
31 | { |
||
32 | /** |
||
33 | * @var BackupInterface[] |
||
34 | */ |
||
35 | protected $backups; |
||
36 | |||
37 | /** |
||
38 | * @var string |
||
39 | */ |
||
40 | protected $directory; |
||
41 | |||
42 | /** |
||
43 | * @var Filesystem |
||
44 | */ |
||
45 | private $filesystem; |
||
46 | |||
47 | 4 | public function __construct($directory, Filesystem $filesystem = null) |
|
48 | { |
||
49 | 4 | $this->directory = $directory; |
|
50 | 4 | $this->filesystem = is_null($filesystem) ? new Filesystem() : $filesystem; |
|
51 | |||
52 | 4 | if (!$this->filesystem->exists($this->directory)) { |
|
53 | |||
54 | 2 | $this->filesystem->mkdir($this->directory); |
|
55 | |||
56 | 4 | } elseif (!is_dir($this->directory)) { |
|
57 | throw new \RuntimeException(sprintf('Provided location "%s" is not directory.', $this->directory)); |
||
58 | 4 | } elseif (!is_writable($this->directory)) { |
|
59 | throw new \RuntimeException(sprintf('Provided location "%s" is not writeable.', $this->directory)); |
||
60 | } |
||
61 | 4 | } |
|
62 | |||
63 | /** |
||
64 | * {@inheritdoc} |
||
65 | */ |
||
66 | 4 | public function push(BackupInterface $backup) |
|
67 | { |
||
68 | 4 | $backupDirectory = sprintf('%s%s%s', rtrim($this->directory, DIRECTORY_SEPARATOR), DIRECTORY_SEPARATOR, $backup->getName()); |
|
69 | 4 | $this->filesystem->mkdir($backupDirectory); |
|
70 | |||
71 | 4 | $existingBackupFiles = array(); |
|
72 | |||
73 | 4 | foreach (Finder::create()->in($backupDirectory)->files() as $existingFile) { |
|
74 | $file = File::fromLocal($existingFile, $backupDirectory); |
||
75 | $existingBackupFiles[$file->getRelativePath()] = $file; |
||
76 | 4 | } |
|
77 | |||
78 | 4 | foreach ($backup->getFiles() as $backupFile) { |
|
79 | |||
80 | try { |
||
81 | 4 | $this->filesystem->copy($backupFile->getPath(), $filePath = sprintf('%s%s%s', $backupDirectory, DIRECTORY_SEPARATOR, $backupFile->getRelativePath())); |
|
82 | 4 | $this->filesystem->touch($filePath, $backupFile->getModifiedAt()->getTimestamp()); |
|
83 | 4 | } catch (\Exception $e) { |
|
84 | throw new DestinationException(sprintf('Unable to backup file "%s" to destination "%s".', $backupFile->getPath(), $this->directory), 0, $e); |
||
85 | } |
||
86 | |||
87 | 4 | if (array_key_exists($backupFile->getRelativePath(), $existingBackupFiles) && $existingBackupFiles[$backupFile->getRelativePath()]) { |
|
88 | unset($existingBackupFiles[$backupFile->getRelativePath()]); |
||
89 | } |
||
90 | 4 | } |
|
91 | |||
92 | 4 | $this->filesystem->remove($existingBackupFiles); |
|
93 | 4 | $this->removeEmptyDirectories($backupDirectory); |
|
94 | |||
95 | 4 | if (!empty($this->backups)) { |
|
96 | $this->backups[] = $backup; |
||
97 | } |
||
98 | 4 | } |
|
99 | |||
100 | /** |
||
101 | * {@inheritdoc} |
||
102 | */ |
||
103 | public function getIterator() |
||
111 | |||
112 | /** |
||
113 | * {@inheritdoc} |
||
114 | */ |
||
115 | 4 | public function get($name) |
|
116 | { |
||
117 | 4 | if (is_null($this->backups)) { |
|
118 | $this->load(); |
||
119 | } |
||
120 | |||
121 | 4 | return $this->backups[$name]; |
|
122 | } |
||
123 | |||
124 | /** |
||
125 | * {@inheritdoc} |
||
126 | */ |
||
127 | 4 | public function has($name) |
|
128 | { |
||
129 | 4 | if (is_null($this->backups)) { |
|
130 | 4 | $this->load(); |
|
131 | 4 | } |
|
132 | |||
133 | 4 | return array_key_exists($name, $this->backups); |
|
134 | } |
||
135 | |||
136 | /** |
||
137 | * {@inheritdoc} |
||
138 | */ |
||
139 | public function delete($name) |
||
151 | |||
152 | /** |
||
153 | * {@inheritdoc} |
||
154 | */ |
||
155 | public function all() |
||
163 | |||
164 | /** |
||
165 | * Load backups from destination. |
||
166 | * |
||
167 | * @return BackupInterface[] |
||
168 | */ |
||
169 | 4 | protected function load() |
|
170 | { |
||
171 | 4 | $this->backups = array(); |
|
172 | |||
173 | /** |
||
174 | * @var \SplFileInfo $backupDirectory |
||
175 | */ |
||
176 | 4 | foreach (Finder::create()->in($this->directory)->depth(0)->directories()->sortByModifiedTime() as $backupDirectory) { |
|
177 | |||
178 | 4 | $backup = new Backup($backupDirectory->getBasename(), array(), 0, $backupDirectory->getCTime(), $backupDirectory->getMTime()); |
|
179 | |||
180 | /** |
||
181 | * @var \SplFileInfo $backupFile |
||
182 | */ |
||
183 | 4 | foreach (Finder::create()->in($backupDirectory->getPathname())->files() as $backupFile) { |
|
184 | |||
185 | 4 | $backup->addFile(File::fromSplFileInfo($backupFile, $backupDirectory->getPathname())); |
|
186 | 4 | } |
|
187 | |||
188 | 4 | $this->backups[$backup->getName()] = $backup; |
|
189 | 4 | } |
|
190 | 4 | } |
|
191 | |||
192 | /** |
||
193 | * Remove empty directories from destination. |
||
194 | * |
||
195 | * @param $backupDirectory |
||
196 | */ |
||
197 | 4 | protected function removeEmptyDirectories($backupDirectory) |
|
198 | { |
||
199 | /** |
||
200 | * @var \SplFileInfo $dir |
||
201 | */ |
||
202 | 4 | foreach (Finder::create()->directories()->in($backupDirectory)->depth(0) as $dir) { |
|
203 | |||
204 | 2 | if (Finder::create()->files()->in($dir->getPathname())->count() > 0) { |
|
205 | 2 | $this->removeEmptyDirectories($dir->getPathname()); |
|
206 | 2 | } else { |
|
207 | $this->filesystem->remove($dir->getPathname()); |
||
208 | } |
||
209 | 4 | } |
|
210 | 4 | } |
|
211 | |||
212 | /** |
||
213 | * {@inheritdoc} |
||
214 | */ |
||
215 | public function count() |
||
219 | } |
||
220 |