Issues (155)

src/Drivers/AlchemyZippy.php (2 issues)

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
Documentation Bug introduced by
It seems like false of type false is incompatible with the declared type Alchemy\Zippy\Zippy of property $zippy.

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..

Loading history...
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
Documentation Bug introduced by
Are you sure the doc-type for parameter $password is correct as it would always require null to be passed?
Loading history...
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