Issues (155)

src/Drivers/Rar.php (3 issues)

1
<?php
2
namespace wapmorgan\UnifiedArchive\Drivers;
3
4
use Exception;
5
use wapmorgan\UnifiedArchive\Abilities;
6
use wapmorgan\UnifiedArchive\ArchiveEntry;
7
use wapmorgan\UnifiedArchive\ArchiveInformation;
8
use wapmorgan\UnifiedArchive\Drivers\Basic\BasicExtensionDriver;
9
use wapmorgan\UnifiedArchive\Formats;
10
11
class Rar extends BasicExtensionDriver
12
{
13
    const NONE_RAR_COMPRESSION = 48;
14
    const EXTENSION_NAME = 'rar';
15
16
    /** @var \RarArchive */
17
    protected $rar;
18
19
    /**
20
     * @inheritDoc
21
     */
22 1
    public static function getDescription()
23
    {
24
        return 'adapter for ext-rar' . (self::isInstalled() ? ' (' . phpversion('rar') . ')' : null);
25 1
    }
26
27
    /**
28
     * @inheritDoc
29
     */
30
    public static function getInstallationInstruction()
31
    {
32
        return 'install [rar] extension.' . "\n" . 'Can be installed with pecl: `pecl install rar`';
33
    }
34
35
    /**
36
     * @return array
37
     */
38
    public static function getFormats()
39
    {
40
        return [
41
            Formats::RAR,
42
        ];
43
    }
44
45
    /**
46
     * @param $format
47
     * @return array
48
     */
49
    public static function getFormatAbilities($format)
50
    {
51
        if (!static::isInstalled()) {
52
            return [];
53
        }
54
        switch ($format) {
55
            case Formats::RAR:
56
                return [
57
                    Abilities::OPEN,
58
                    Abilities::OPEN_ENCRYPTED,
59
                    Abilities::OPEN_VOLUMED,
60
                    Abilities::EXTRACT_CONTENT,
61
                    Abilities::STREAM_CONTENT,
62
                ];
63
        }
64
    }
65
66
    /**
67
     * @inheritDoc
68
     */
69
    public function __construct($archiveFileName, $format, $password = null)
70
    {
71
        parent::__construct($archiveFileName, $format);
72
        \RarException::setUsingExceptions(true);
73
        $this->open($archiveFileName, $password);
74
    }
75
76
    /**
77
     * @param $archiveFileName
78
     * @param $password
79
     * @throws Exception
80
     */
81
    protected function open($archiveFileName, $password)
82
    {
83
        $this->rar = \RarArchive::open($archiveFileName, $password, function ($vol) {
0 ignored issues
show
The parameter $vol is not used and could be removed. ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-unused  annotation

83
        $this->rar = \RarArchive::open($archiveFileName, $password, function (/** @scrutinizer ignore-unused */ $vol) {

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
84
            throw new Exception('Could not open volumed Rar archive');
85
        });
86
        $this->rar->setAllowBroken(true);
87
        if ($this->rar === false) {
88
            throw new Exception('Could not open Rar archive');
89
        }
90
    }
91
92
    /**
93
     * Rar format destructor
94
     */
95
    public function __destruct()
96
    {
97
        $this->rar->close();
98
    }
99
100
    /**
101
     * @return ArchiveInformation
102
     */
103
    public function getArchiveInformation()
104
    {
105
        $information = new ArchiveInformation();
106
        foreach ($this->rar->getEntries() as $i => $entry) {
107
            if ($entry->isDirectory()) continue;
108
            $information->files[] = $entry->getName();
109
            $information->compressedFilesSize += $entry->getPackedSize();
110
            $information->uncompressedFilesSize += $entry->getUnpackedSize();
111
        }
112
        return $information;
113
    }
114
115
    /**
116
     * @return string|null
117
     */
118
    public function getComment()
119
    {
120
        return $this->rar->getComment();
121
    }
122
123
    /**
124
     * @return array
125
     */
126
    public function getFileNames()
127
    {
128
        $files = [];
129
        foreach ($this->rar->getEntries() as $i => $entry) {
130
            if ($entry->isDirectory()) continue;
131
            $files[] = $entry->getName();
132
        }
133
        return $files;
134
    }
135
136
    /**
137
     * @param string $fileName
138
     *
139
     * @return bool
140
     */
141
    public function isFileExists($fileName)
142
    {
143
        return $this->rar->getEntry($fileName) !== false;
144
    }
145
146
    /**
147
     * @param string $fileName
148
     *
149
     * @return ArchiveEntry|false
150
     */
151
    public function getFileData($fileName)
152
    {
153
        $entry = $this->rar->getEntry($fileName);
154
        return new ArchiveEntry($fileName, $entry->getPackedSize(), $entry->getUnpackedSize(),
155
            strtotime($entry->getFileTime()), $entry->getMethod() != self::NONE_RAR_COMPRESSION);
156
    }
157
158
    /**
159
     * @param string $fileName
160
     *
161
     * @return string|false
162
     */
163
    public function getFileContent($fileName)
164
    {
165
        $entry = $this->rar->getEntry($fileName);
166
        if ($entry->isDirectory()) return false;
167
        return stream_get_contents($entry->getStream());
168
    }
169
170
    /**
171
     * @param string $fileName
172
     *
173
     * @return bool|resource|string
174
     */
175
    public function getFileStream($fileName)
176
    {
177
        $entry = $this->rar->getEntry($fileName);
178
        if ($entry->isDirectory()) return false;
0 ignored issues
show
Bug Best Practice introduced by
The expression return false returns the type false which is incompatible with the return type mandated by wapmorgan\UnifiedArchive...Driver::getFileStream() of resource.

In the issue above, the returned value is violating the contract defined by the mentioned interface.

Let's take a look at an example:

interface HasName {
    /** @return string */
    public function getName();
}

class Name {
    public $name;
}

class User implements HasName {
    /** @return string|Name */
    public function getName() {
        return new Name('foo'); // This is a violation of the ``HasName`` interface
                                // which only allows a string value to be returned.
    }
}
Loading history...
179
        return $entry->getStream();
180
    }
181
182
    /**
183
     * @param string $outputFolder
184
     * @param array  $files
185
     *
186
     * @return false|int
187
     */
188
    public function extractFiles($outputFolder, array $files)
189
    {
190
        $count = 0;
191
        foreach ($files as $file) {
192
            if ($this->rar->getEntry($file)->extract($outputFolder)) {
193
                $count++;
194
            }
195
        }
196
        return $count;
197
    }
198
199
    /**
200
     * @param string $outputFolder
201
     *
202
     * @return false|resource
203
     */
204
    public function extractArchive($outputFolder)
205
    {
206
        return $this->extractFiles($outputFolder, $this->getFileNames());
0 ignored issues
show
Bug Best Practice introduced by
The expression return $this->extractFil... $this->getFileNames()) returns the type integer which is incompatible with the documented return type false|resource.
Loading history...
207
    }
208
}
209