1 | <?php |
||
2 | namespace wapmorgan\UnifiedArchive\Drivers; |
||
3 | |||
4 | use Alchemy\Zippy\Archive\Member; |
||
5 | use Alchemy\Zippy\Exception\NoAdapterOnPlatformException; |
||
6 | use Alchemy\Zippy\Zippy; |
||
7 | use Exception; |
||
8 | use wapmorgan\UnifiedArchive\Abilities; |
||
9 | use wapmorgan\UnifiedArchive\ArchiveEntry; |
||
10 | use wapmorgan\UnifiedArchive\ArchiveInformation; |
||
11 | use wapmorgan\UnifiedArchive\Drivers\Basic\BasicUtilityDriver; |
||
12 | use wapmorgan\UnifiedArchive\Exceptions\ArchiveCreationException; |
||
13 | use wapmorgan\UnifiedArchive\Exceptions\ArchiveExtractionException; |
||
14 | use wapmorgan\UnifiedArchive\Exceptions\ArchiveModificationException; |
||
15 | use wapmorgan\UnifiedArchive\Exceptions\UnsupportedOperationException; |
||
16 | use wapmorgan\UnifiedArchive\Formats; |
||
17 | |||
18 | class AlchemyZippy extends BasicUtilityDriver |
||
19 | { |
||
20 | /** |
||
21 | * @var Zippy |
||
22 | */ |
||
23 | protected static $zippy; |
||
24 | |||
25 | /** |
||
26 | * @var string |
||
27 | */ |
||
28 | protected $fileName; |
||
29 | |||
30 | /** |
||
31 | * @var \Alchemy\Zippy\Archive\ArchiveInterface |
||
32 | */ |
||
33 | protected $archive; |
||
34 | |||
35 | /** |
||
36 | * @var array |
||
37 | */ |
||
38 | protected $files; |
||
39 | |||
40 | /** |
||
41 | * @var Member[] |
||
42 | */ |
||
43 | protected $members; |
||
44 | |||
45 | /** |
||
46 | * @inheritDoc |
||
47 | */ |
||
48 | public static function getDescription() |
||
49 | { |
||
50 | return 'php-library and console programs'; |
||
51 | } |
||
52 | 1 | ||
53 | public static function isInstalled() |
||
54 | { |
||
55 | 1 | self::init(); |
|
56 | return static::$zippy !== false; |
||
57 | } |
||
58 | |||
59 | /** |
||
60 | * @inheritDoc |
||
61 | */ |
||
62 | 4 | public static function getInstallationInstruction() |
|
63 | { |
||
64 | 4 | self::init(); |
|
65 | 4 | return 'install library [alchemy/zippy]: `composer require alchemy/zippy`' . "\n" . ' and console programs (tar, zip): `apt install tar zip` - depends on OS' |
|
66 | . "\n" . 'If you install SevenZip and AlchemyZippy:' . "\n" . |
||
67 | '1. You should specify symfony/console version before installation to any **3.x.x version**:' . "\n" . '`composer require symfony/process:~3.4`, because they require different `symfony/process` versions.' . "\n" . |
||
68 | 4 | '2. Install archive7z version 4.0.0: `composer require gemorroj/archive7z:~4.0`'; |
|
69 | } |
||
70 | |||
71 | /** |
||
72 | * @return mixed|void |
||
73 | */ |
||
74 | 4 | public static function getFormats() |
|
75 | { |
||
76 | 4 | return [ |
|
77 | Formats::ZIP, |
||
78 | 4 | Formats::TAR, |
|
79 | 4 | Formats::TAR_GZIP, |
|
80 | Formats::TAR_BZIP, |
||
81 | ]; |
||
82 | } |
||
83 | |||
84 | protected static function init() |
||
85 | { |
||
86 | if (!class_exists('\Alchemy\Zippy\Zippy')) |
||
87 | static::$zippy = false; |
||
0 ignored issues
–
show
|
|||
88 | else if (static::$zippy === null) |
||
89 | static::$zippy = Zippy::load(); |
||
90 | } |
||
91 | |||
92 | /** |
||
93 | * @param $format |
||
94 | * @return array |
||
95 | */ |
||
96 | public static function getFormatAbilities($format) |
||
97 | { |
||
98 | static::init(); |
||
99 | |||
100 | if (static::$zippy === false) |
||
101 | return []; |
||
102 | |||
103 | switch ($format) { |
||
104 | case Formats::TAR_BZIP: |
||
105 | case Formats::TAR: |
||
106 | case Formats::TAR_GZIP: |
||
107 | case Formats::ZIP: |
||
108 | if (static::checkAdapterFor($format) === false) { |
||
109 | return []; |
||
110 | } |
||
111 | |||
112 | return [ |
||
113 | Abilities::OPEN, |
||
114 | Abilities::EXTRACT_CONTENT, |
||
115 | Abilities::APPEND, |
||
116 | Abilities::DELETE, |
||
117 | Abilities::CREATE, |
||
118 | ]; |
||
119 | } |
||
120 | } |
||
121 | |||
122 | /** |
||
123 | * @param $format |
||
124 | * @param $adapter |
||
125 | * @return bool |
||
126 | */ |
||
127 | protected static function checkAdapterFor($format, &$adapter = null) |
||
128 | { |
||
129 | try { |
||
130 | $adapter = static::$zippy->getAdapterFor($format); |
||
131 | return true; |
||
132 | } catch (NoAdapterOnPlatformException $e) { |
||
133 | return false; |
||
134 | } |
||
135 | } |
||
136 | |||
137 | /** |
||
138 | * @param array $files |
||
139 | * @param string $archiveFileName |
||
140 | * @param int $archiveFormat |
||
141 | * @param int $compressionLevel |
||
142 | * @param null $password |
||
0 ignored issues
–
show
|
|||
143 | * @param $fileProgressCallable |
||
144 | * @return int |
||
145 | * @throws ArchiveCreationException |
||
146 | * @throws UnsupportedOperationException |
||
147 | */ |
||
148 | public static function createArchive( |
||
149 | array $files, |
||
150 | $archiveFileName, |
||
151 | $archiveFormat, |
||
152 | $compressionLevel = self::COMPRESSION_AVERAGE, |
||
153 | $password = null, |
||
154 | $fileProgressCallable = null |
||
155 | ) |
||
156 | { |
||
157 | if ($password !== null) { |
||
158 | throw new UnsupportedOperationException('AlchemyZippy could not encrypt an archive'); |
||
159 | } |
||
160 | |||
161 | try { |
||
162 | $archive = static::$zippy->create($archiveFileName, $files); |
||
163 | } catch (Exception $e) { |
||
164 | throw new ArchiveCreationException('Could not create archive: '.$e->getMessage(), $e->getCode(), $e); |
||
165 | } |
||
166 | return count($files); |
||
167 | } |
||
168 | |||
169 | /** |
||
170 | * @inheritDoc |
||
171 | */ |
||
172 | public function __construct($archiveFileName, $format, $password = null) |
||
173 | { |
||
174 | parent::__construct($archiveFileName, $format); |
||
175 | $this->archive = static::$zippy->open($archiveFileName); |
||
176 | } |
||
177 | |||
178 | /** |
||
179 | * @inheritDoc |
||
180 | */ |
||
181 | public function getArchiveInformation() |
||
182 | { |
||
183 | $this->files = []; |
||
184 | $information = new ArchiveInformation(); |
||
185 | |||
186 | foreach ($this->archive->getMembers() as $member) { |
||
187 | if ($member->isDir()) |
||
188 | continue; |
||
189 | |||
190 | $this->files[] = $information->files[] = str_replace('\\', '/', $member->getLocation()); |
||
191 | $this->members[str_replace('\\', '/', $member->getLocation())] = $member; |
||
192 | $information->compressedFilesSize += (int)$member->getSize(); |
||
193 | $information->uncompressedFilesSize += (int)$member->getSize(); |
||
194 | } |
||
195 | return $information; |
||
196 | } |
||
197 | |||
198 | /** |
||
199 | * @inheritDoc |
||
200 | */ |
||
201 | public function getFileNames() |
||
202 | { |
||
203 | return $this->files; |
||
204 | } |
||
205 | |||
206 | /** |
||
207 | * @inheritDoc |
||
208 | */ |
||
209 | public function isFileExists($fileName) |
||
210 | { |
||
211 | return in_array($fileName, $this->files); |
||
212 | } |
||
213 | |||
214 | protected function getMember($fileName) |
||
215 | { |
||
216 | return $this->members[$fileName]; |
||
217 | |||
218 | // foreach ($this->archive->getMembers() as $member) { |
||
219 | // if ($member->isDir()) |
||
220 | // continue; |
||
221 | // if ($member->getLocation() === $fileName) |
||
222 | // return $member; |
||
223 | // } |
||
224 | // return null; |
||
225 | } |
||
226 | |||
227 | /** |
||
228 | * @inheritDoc |
||
229 | */ |
||
230 | public function getFileData($fileName) |
||
231 | { |
||
232 | $member = $this->getMember($fileName); |
||
233 | return new ArchiveEntry($member->getLocation(), $member->getSize(), $member->getSize(), strtotime($member->getLastModifiedDate()), true); |
||
234 | } |
||
235 | |||
236 | /** |
||
237 | * @inheritDoc |
||
238 | */ |
||
239 | public function getFileContent($fileName) |
||
240 | { |
||
241 | $member = $this->getMember($fileName); |
||
242 | return (string)$member; |
||
243 | } |
||
244 | |||
245 | /** |
||
246 | * @inheritDoc |
||
247 | */ |
||
248 | public function getFileStream($fileName) |
||
249 | { |
||
250 | $member = $this->getMember($fileName); |
||
251 | return self::wrapStringInStream((string)$member); |
||
252 | } |
||
253 | |||
254 | /** |
||
255 | * @inheritDoc |
||
256 | */ |
||
257 | public function extractFiles($outputFolder, array $files) |
||
258 | { |
||
259 | try { |
||
260 | foreach ($files as $file) { |
||
261 | $member = $this->getMember($file); |
||
262 | $member->extract($outputFolder); |
||
263 | } |
||
264 | } catch (Exception $e) { |
||
265 | throw new ArchiveExtractionException('Could not extract archive: '.$e->getMessage(), $e->getCode(), $e); |
||
266 | } |
||
267 | return count($files); |
||
268 | } |
||
269 | |||
270 | /** |
||
271 | * @inheritDoc |
||
272 | */ |
||
273 | public function extractArchive($outputFolder) |
||
274 | { |
||
275 | try { |
||
276 | $this->archive->extract($outputFolder); |
||
277 | } catch (Exception $e) { |
||
278 | throw new ArchiveExtractionException('Could not extract archive: '.$e->getMessage(), $e->getCode(), $e); |
||
279 | } |
||
280 | return count($this->files); |
||
281 | } |
||
282 | |||
283 | /** |
||
284 | * @inheritDoc |
||
285 | */ |
||
286 | public function deleteFiles(array $files) |
||
287 | { |
||
288 | $members = []; |
||
289 | try { |
||
290 | foreach ($files as $file) { |
||
291 | $members[] = $this->getMember($file); |
||
292 | } |
||
293 | $this->archive->removeMembers($members); |
||
294 | } catch (Exception $e) { |
||
295 | throw new ArchiveModificationException('Could not remove files from archive: '.$e->getMessage(), $e->getCode(), $e); |
||
296 | } |
||
297 | return count($files); |
||
298 | } |
||
299 | |||
300 | /** |
||
301 | * @inheritDoc |
||
302 | */ |
||
303 | public function addFiles(array $files) |
||
304 | { |
||
305 | $added = 0; |
||
306 | try { |
||
307 | foreach ($files as $localName => $filename) { |
||
308 | if (is_null($filename)) { |
||
309 | // $this->archive->addEmptyDir($localName); |
||
310 | } else { |
||
311 | $this->archive->addMembers([$filename => $localName]); |
||
312 | $added++; |
||
313 | } |
||
314 | } |
||
315 | } catch (Exception $e) { |
||
316 | throw new ArchiveModificationException('Could not add file "'.$filename.'": '.$e->getMessage(), $e->getCode()); |
||
317 | } |
||
318 | $this->getArchiveInformation(); |
||
319 | return $added; |
||
320 | } |
||
321 | |||
322 | /** |
||
323 | * @param string $inArchiveName |
||
324 | * @param string $content |
||
325 | * @return bool |
||
326 | */ |
||
327 | public function addFileFromString($inArchiveName, $content) |
||
328 | { |
||
329 | $fp = fopen('php://memory', 'w'); |
||
330 | fwrite($fp, $content); |
||
331 | rewind($fp); |
||
332 | $this->archive->addMembers([$inArchiveName => $fp]); |
||
333 | fclose($fp); |
||
334 | return true; |
||
335 | } |
||
336 | } |
||
337 |
Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.
Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..