Passed
Push — master ( b1d4f6...7824cd )
by f
10:25
created

AlchemyZippy::createArchive()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 19
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 12

Importance

Changes 0
Metric Value
cc 3
eloc 7
c 0
b 0
f 0
nc 3
nop 6
dl 0
loc 19
ccs 0
cts 4
cp 0
crap 12
rs 10
1
<?php
2
namespace wapmorgan\UnifiedArchive\Drivers;
3
4
use Alchemy\Zippy\Archive\Member;
0 ignored issues
show
Bug introduced by
The type Alchemy\Zippy\Archive\Member was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
5
use Alchemy\Zippy\Exception\NoAdapterOnPlatformException;
0 ignored issues
show
Bug introduced by
The type Alchemy\Zippy\Exception\...pterOnPlatformException was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
6
use Alchemy\Zippy\Zippy;
0 ignored issues
show
Bug introduced by
The type Alchemy\Zippy\Zippy was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
7
use Exception;
8
use wapmorgan\UnifiedArchive\ArchiveEntry;
9
use wapmorgan\UnifiedArchive\ArchiveInformation;
10
use wapmorgan\UnifiedArchive\Exceptions\ArchiveCreationException;
11
use wapmorgan\UnifiedArchive\Exceptions\ArchiveExtractionException;
12
use wapmorgan\UnifiedArchive\Exceptions\ArchiveModificationException;
13
use wapmorgan\UnifiedArchive\Exceptions\UnsupportedOperationException;
14
use wapmorgan\UnifiedArchive\Formats;
15
use wapmorgan\UnifiedArchive\Drivers\BasicDriver;
16
17
class AlchemyZippy extends BasicDriver
18
{
19
    /**
20
     * @var Zippy
21
     */
22
    protected static $zippy;
23
24
    /**
25
     * @var string
26
     */
27
    protected $fileName;
28
29
    /**
30
     * @var \Alchemy\Zippy\Archive\ArchiveInterface
0 ignored issues
show
Bug introduced by
The type Alchemy\Zippy\Archive\ArchiveInterface was not found. Maybe you did not declare it correctly or list all dependencies?

The issue could also be caused by a filter entry in the build configuration. If the path has been excluded in your configuration, e.g. excluded_paths: ["lib/*"], you can move it to the dependency path list as follows:

filter:
    dependency_paths: ["lib/*"]

For further information see https://scrutinizer-ci.com/docs/tools/php/php-scrutinizer/#list-dependency-paths

Loading history...
31
     */
32
    protected $archive;
33
34
    /**
35
     * @var array
36
     */
37
    protected $files;
38
39
    /**
40
     * @var string
41
     */
42
    protected $format;
43
44
    /**
45
     * @var Member[]
46
     */
47
    protected $members;
48
49
    /**
50
     * @return mixed|void
51
     */
52 1
    public static function getSupportedFormats()
53
    {
54
        return [
55 1
            Formats::ZIP,
56
            Formats::TAR,
57
            Formats::TAR_GZIP,
58
            Formats::TAR_BZIP,
59
        ];
60
    }
61
62 4
    protected static function init()
63
    {
64 4
        if (!class_exists('\Alchemy\Zippy\Zippy'))
65 4
            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...
66
        else if (static::$zippy === null)
67
            static::$zippy = Zippy::load();
68 4
    }
69
70
    /**
71
     * @param $format
72
     * @return array
73
     */
74 4
    public static function checkFormatSupport($format)
75
    {
76 4
        static::init();
77
78 4
        if (static::$zippy === false)
0 ignored issues
show
introduced by
The condition static::zippy === false is always false.
Loading history...
79 4
            return [];
80
81
        switch ($format) {
82
            case Formats::TAR_BZIP:
83
            case Formats::TAR:
84
            case Formats::TAR_GZIP:
85
            case Formats::ZIP:
86
                if (static::checkAdapterFor($format) === false) {
87
                    return [];
88
                }
89
90
                return [
91
                    BasicDriver::OPEN,
92
                    BasicDriver::EXTRACT_CONTENT,
93
                    BasicDriver::APPEND,
94
                    BasicDriver::DELETE,
95
                    BasicDriver::CREATE,
96
                ];
97
        }
98
    }
99
100
    /**
101
     * @inheritDoc
102
     */
103
    public static function getDescription()
104
    {
105
        return 'php-library and console programs';
106
    }
107
108
    /**
109
     * @inheritDoc
110
     */
111
    public static function getInstallationInstruction()
112
    {
113
        self::init();
114
        return static::$zippy === false
0 ignored issues
show
introduced by
The condition static::zippy === false is always false.
Loading history...
115
            ? 'install library [alchemy/zippy]: `composer require alchemy/zippy`' . "\n"  . ' and console programs (tar, zip): `apt install tar zip` - depends on OS'
116
            . "\n" . 'If you install SevenZip and AlchemyZippy:' . "\n" .
117
'1. You should specify symfony/console version before installation to any **3.x.x version**: `composer require symfony/process:~3.4`, because they require different `symfony/process` versions.' . "\n" .
118
'2. Install archive7z version 4.0.0: `composer require gemorroj/archive7z:~4.0`'
119
            : null;
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) {
0 ignored issues
show
introduced by
The condition $password !== null is always false.
Loading history...
158
            throw new UnsupportedOperationException('AlchemyZippy could not encrypt an archive');
159
        }
160
161
        try {
162
            $archive = static::$zippy->create($archiveFileName, $files);
0 ignored issues
show
Unused Code introduced by
The assignment to $archive is dead and can be removed.
Loading history...
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
        $this->fileName = $archiveFileName;
175
        $this->format = $format;
176
        $this->archive = static::$zippy->open($archiveFileName);
177
    }
178
179
    /**
180
     * @inheritDoc
181
     */
182
    public function getArchiveInformation()
183
    {
184
        $this->files = [];
185
        $information = new ArchiveInformation();
186
187
        foreach ($this->archive->getMembers() as $member) {
188
            if ($member->isDir())
189
                continue;
190
191
            $this->files[] = $information->files[] = str_replace('\\', '/', $member->getLocation());
192
            $this->members[str_replace('\\', '/', $member->getLocation())] = $member;
193
            $information->compressedFilesSize += (int)$member->getSize();
194
            $information->uncompressedFilesSize += (int)$member->getSize();
195
        }
196
        return $information;
197
    }
198
199
    /**
200
     * @inheritDoc
201
     */
202
    public function getFileNames()
203
    {
204
        return $this->files;
205
    }
206
207
    /**
208
     * @inheritDoc
209
     */
210
    public function isFileExists($fileName)
211
    {
212
        return in_array($fileName, $this->files);
213
    }
214
215
    protected function getMember($fileName)
216
    {
217
        return $this->members[$fileName];
218
219
//        foreach ($this->archive->getMembers() as $member) {
220
//            if ($member->isDir())
221
//                continue;
222
//            if ($member->getLocation() === $fileName)
223
//                return $member;
224
//        }
225
//        return null;
226
    }
227
228
    /**
229
     * @inheritDoc
230
     */
231
    public function getFileData($fileName)
232
    {
233
        $member = $this->getMember($fileName);
234
        return new ArchiveEntry($member->getLocation(), $member->getSize(), $member->getSize(), strtotime($member->getLastModifiedDate()), true);
235
    }
236
237
    /**
238
     * @inheritDoc
239
     */
240
    public function getFileContent($fileName)
241
    {
242
        $member = $this->getMember($fileName);
243
        return (string)$member;
244
    }
245
246
    /**
247
     * @inheritDoc
248
     */
249
    public function getFileStream($fileName)
250
    {
251
        $member = $this->getMember($fileName);
252
        return self::wrapStringInStream((string)$member);
253
    }
254
255
    /**
256
     * @inheritDoc
257
     */
258
    public function extractFiles($outputFolder, array $files)
259
    {
260
        try {
261
            foreach ($files as $file) {
262
                $member = $this->getMember($file);
263
                $member->extract($outputFolder);
264
            }
265
        } catch (Exception $e) {
266
            throw new ArchiveExtractionException('Could not extract archive: '.$e->getMessage(), $e->getCode(), $e);
267
        }
268
        return count($files);
269
    }
270
271
    /**
272
     * @inheritDoc
273
     */
274
    public function extractArchive($outputFolder)
275
    {
276
        try {
277
            $this->archive->extract($outputFolder);
278
        } catch (Exception $e) {
279
            throw new ArchiveExtractionException('Could not extract archive: '.$e->getMessage(), $e->getCode(), $e);
280
        }
281
        return count($this->files);
282
    }
283
284
    /**
285
     * @inheritDoc
286
     */
287
    public function deleteFiles(array $files)
288
    {
289
        $members = [];
290
        try {
291
            foreach ($files as $file) {
292
                $members[] = $this->getMember($file);
293
            }
294
            $this->archive->removeMembers($members);
295
        } catch (Exception $e) {
296
            throw new ArchiveModificationException('Could not remove files from archive: '.$e->getMessage(), $e->getCode(), $e);
297
        }
298
        return count($files);
299
    }
300
301
    /**
302
     * @inheritDoc
303
     */
304
    public function addFiles(array $files)
305
    {
306
        $added = 0;
307
        try {
308
            foreach ($files as $localName => $filename) {
309
                if (is_null($filename)) {
310
//                    $this->archive->addEmptyDir($localName);
311
                } else {
312
                    $this->archive->addMembers([$filename => $localName]);
313
                    $added++;
314
                }
315
            }
316
        } catch (Exception $e) {
317
            throw new ArchiveModificationException('Could not add file "'.$filename.'": '.$e->getMessage(), $e->getCode());
318
        }
319
        $this->getArchiveInformation();
320
        return $added;
321
    }
322
323
    /**
324
     * @param string $inArchiveName
325
     * @param string $content
326
     * @return bool
327
     */
328
    public function addFileFromString($inArchiveName, $content)
329
    {
330
        $fp = fopen('php://memory', 'w');
331
        fwrite($fp, $content);
332
        rewind($fp);
333
        $this->archive->addMembers([$inArchiveName => $fp]);
334
        fclose($fp);
335
        return true;
336
    }
337
}