GdaemonFiles   C
last analyzed

Complexity

Total Complexity 53

Size/Duplication

Total Lines 368
Duplicated Lines 0 %

Test Coverage

Coverage 98.82%

Importance

Changes 4
Bugs 1 Features 0
Metric Value
eloc 195
c 4
b 1
f 0
dl 0
loc 368
ccs 167
cts 169
cp 0.9882
rs 6.96
wmc 53

12 Methods

Rating   Name   Duplication   Size   Complexity  
B put() 0 60 11
A move() 0 18 3
A delete() 0 17 3
A metadata() 0 26 4
A chmod() 0 17 3
B get() 0 54 10
A rename() 0 3 1
A listFiles() 0 29 5
A mkdir() 0 19 3
A copy() 0 18 3
A exist() 0 3 1
B directoryContents() 0 35 6

How to fix   Complexity   

Complex Class

Complex classes like GdaemonFiles often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use GdaemonFiles, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
namespace Knik\Gameap;
4
5
use Knik\Gameap\Exception\GdaemonClientException;
6
use InvalidArgumentException;
7
8
class GdaemonFiles extends Gdaemon
9
{
10
    const FSERV_AUTH            = 1;
11
    const FSERV_FILESEND        = 3;
12
    const FSERV_READDIR         = 4;
13
    const FSERV_MKDIR           = 5;
14
    const FSERV_MOVE            = 6;
15
    const FSERV_REMOVE          = 7;
16
    const FSERV_FILEINFO        = 8;
17
    const FSERV_CHMOD           = 9;
18
19
    const FSERV_UPLOAD_TO_SERVER        = 1;
20
    const FSERV_DOWNLOAD_FR_SERVER      = 2;
21
22
    const FSERV_STATUS_ERROR                = 1;
23
    const FSERV_STATUS_UNKNOWN_COMMAND      = 3;
24
    const FSERV_STATUS_OK                   = 100;
25
    const FSERV_STATUS_FILE_TRANSFER_READY  = 101;
26
27
    const LIST_FILES_WITHOUT_DETAILS  = 0;
28
    const LIST_FILES_WITH_DETAILS     = 1;
29
30
    /**
31
     * @var int
32
     */
33
    protected $mode = self::DAEMON_SERVER_MODE_FILES;
34
35
    /**
36
     * Upload file to server
37
     *
38
     * @param string|resource $locFile path to local file or file stream
39
     * @param string $remFile path to remote file
40
     * @param int $permission
41
     *
42 21
     * @return bool|resource
43
     */
44 21
    public function put($locFile, string $remFile, int $permission = 0644)
45
    {
46 15
        if (is_string($locFile)) {
47 15
            set_error_handler(function () {});
48 11
            $fileHandle = fopen($locFile, 'r');
49 3
            restore_error_handler();
50 1
        } else if (is_resource($locFile)) {
51 3
            $fileHandle = $locFile;
52
        } else {
53
            throw new InvalidArgumentException('Invalid local file');
54 18
        }
55 3
56
        if ($fileHandle === false) {
0 ignored issues
show
introduced by
The condition $fileHandle === false is always false.
Loading history...
57
            throw new GdaemonClientException('File open error');
58 15
        }
59 15
60 15
        $stat = fstat($fileHandle);
61
        $filesize = $stat['size'];
62 15
        unset($stat);
63
64 15
        $message = $this->binn->serialize([
65 15
            self::FSERV_FILESEND,
66 15
            self::FSERV_UPLOAD_TO_SERVER,
67 15
            $remFile,
68 15
            $filesize,
69 15
            true,           // Make dirs
70
            $permission
71 15
        ]);
72
73 15
        $read = $this->writeAndReadSocket($message);
74 15
75 15
        $results = $this->binn->unserialize($read);
76
77 15
        if ($results[0] == self::FSERV_STATUS_OK) {
78 3
            throw new GdaemonClientException('Unexpected \'OK\' status. Expected \'ready to transfer\'');
79 12
        } else if ($results[0] != self::FSERV_STATUS_FILE_TRANSFER_READY) {
80 3
            throw new GdaemonClientException('Couldn\'t upload file: ' . (isset($results[1]) ? $results[1] : 'Unknown'));
81
        }
82
83 9
        while(!feof($fileHandle)) {
84
            $this->writeSocket(fread($fileHandle, $this->maxBufsize));
85
        }
86
87 9
        $read = $this->readSocket();
88
        if (!is_string($read)) {
0 ignored issues
show
introduced by
The condition is_string($read) is always true.
Loading history...
89 9
            throw new GdaemonClientException('Failed to read socket');
90 9
        }
91 9
92
        $results = $this->binn->unserialize($read);
93 9
94 3
        if ($results[0] != self::FSERV_STATUS_OK) {
95
            throw new GdaemonClientException('Couldn\'t send file: ' . ($results[1] ?? 'Unknown'));
96
        }
97 6
98 3
        if (is_resource($locFile)) {
99 3
            rewind($fileHandle);
100
            return $fileHandle;
101 3
        } else {
102 3
            fclose($fileHandle);
103
            return true;
104
        }
105
    }
106
107
    /**
108
     * Download file
109
     *
110
     * @param string $remFile path to remote file
111
     * @param string|resource $locFile path to local file or file stream
112
     *
113
     * @return boolean|resource
114 24
     */
115
    public function get(string $remFile, $locFile)
116 24
    {
117
        if (is_string($locFile)) {
118 18
            set_error_handler(function () {});
119 18
            $fileHandle = fopen($locFile, 'w+b');
120 12
            restore_error_handler();
121 3
        } else if (is_resource($locFile)) {
122 1
            $fileHandle = $locFile;
123 3
        } else {
124
            throw new InvalidArgumentException('Invalid local file');
125
        }
126 21
127 3
        if ($fileHandle === false) {
0 ignored issues
show
introduced by
The condition $fileHandle === false is always false.
Loading history...
128
            throw new GdaemonClientException('File open error');
129
        }
130 18
131
        $message = $this->binn->serialize([
132 18
            self::FSERV_FILESEND,
133 18
            self::FSERV_DOWNLOAD_FR_SERVER,
134 18
            $remFile,
135
        ]);
136 18
137
        $read = $this->writeAndReadSocket($message);
138 18
139 18
        $results = $this->binn->unserialize($read);
140 18
141
        if ($results[0] == self::FSERV_STATUS_OK) {
142 18
            throw new GdaemonClientException('Unexpected `OK` status. Expected `ready to transfer`');
143 3
        } else if ($results[0] != self::FSERV_STATUS_FILE_TRANSFER_READY) {
144 15
            throw new GdaemonClientException('Couldn\'t upload file: ' . (isset($results[1]) ? $results[1] : 'Unknown'));
145 3
        }
146
147
        $filesize = $results[2];
148 12
        $writed = 0;
149
150 12
        while($writed < $filesize) {
151 12
            if ($filesize - $writed > $this->maxBufsize) {
152
                $readlen = $this->maxBufsize;
153 12
            }
154 12
            else {
155 3
                $readlen = $filesize - $writed;
156 1
            }
157
158 12
            $socketRead = $this->readSocket($readlen, true);
159
160
            $writed += fwrite($fileHandle, $socketRead, $readlen);
161 12
        }
162
163 12
        if (is_resource($locFile)) {
164 4
            rewind($fileHandle);
165
            return $fileHandle;
166 12
        } else {
167 3
            fclose($fileHandle);
168 3
            return true;
169
        }
170 9
    }
171 9
172
    public function listFiles(string $directory): array
173
    {
174
        $message = $this->binn->serialize([
175
            self::FSERV_READDIR,
176
            $directory,
177
            self::LIST_FILES_WITHOUT_DETAILS,
178
        ]);
179
180
        $read = $this->writeAndReadSocket($message);
181
182 12
        $results = $this->binn->unserialize($read);
183
184 12
        if ($results[0] != self::FSERV_STATUS_OK) {
185
            throw new GdaemonClientException('GDaemon List files error:' . (isset($results[1]) ? $results[1] : 'Unknown'));
186 12
        }
187 12
188 12
        $filesList = $results[2] ?? [];
189
        $returnList = [];
190 12
191
        foreach($filesList as $file) {
192 12
193
            if (in_array(basename($file[0]), ['.', '..'])) {
194 12
                continue;
195 12
            }
196
197 12
            $returnList[] = basename($file[0]);
198
        }
199 3
200
        return $returnList;
201
    }
202 9
203 9
    public function directoryContents(string $directory): array
204
    {
205 9
        $message = $this->binn->serialize([
206
            self::FSERV_READDIR,
207 9
            $directory,
208 3
            self::LIST_FILES_WITH_DETAILS,
209
        ]);
210
211 9
        $read = $this->writeAndReadSocket($message);
212 3
213
        $results = $this->binn->unserialize($read);
214 9
215
        if ($results[0] != self::FSERV_STATUS_OK) {
216
            // Error
217
            throw new GdaemonClientException('GDaemon List files error:' . (isset($results[1]) ? $results[1] : 'Unknown'));
218
        }
219
220
        $filesList = $results[2];
221 9
        $returnList = [];
222
223 9
        foreach($filesList as $file) {
224
            if (in_array(basename($file[0]), ['.', '..'])) {
225 9
                continue;
226 9
            }
227 9
228
            $returnList[] = [
229 9
                'name' => basename($file[0]),
230
                'size' => $file[1],
231 9
                'mtime' => $file[2],
232
                'type' => ($file[3] == 1) ? 'dir' : 'file',
233 9
                'permissions' => $file[4],
234 9
            ];
235
        }
236 9
237
        return $returnList;
238 3
    }
239
240
    public function mkdir(string $path, int $permissions = 0755): bool
241 6
    {
242 6
        $message = $this->binn->serialize([
243
            self::FSERV_MKDIR,
244 6
            $path,
245 3
            $permissions,
246 3
        ]);
247
248
        $read = $this->writeAndReadSocket($message);
249 3
250 3
        $results = $this->binn->unserialize($read);
251 3
252 3
        if ($results[0] != self::FSERV_STATUS_OK) {
253 3
            throw new GdaemonClientException(
254 3
                'Couldn\'t make directory: ' . isset($results[1]) ? $results[1] : 'Unknown'
255
            );
256 2
        }
257
258 6
        return true;
259
    }
260
261
    public function rename(string $oldPath, string $newPath): bool
262
    {
263
        return $this->move($oldPath, $newPath);
264
    }
265
266
    public function move(string $oldPath, string $newPath): bool
267
    {
268 6
        $message = $this->binn->serialize([
269
            self::FSERV_MOVE,
270 6
            $oldPath,
271
            $newPath,
272 6
            false           // Copy file
273 6
        ]);
274 6
275
        $read = $this->writeAndReadSocket($message);
276 6
277
        $results = $this->binn->unserialize($read);
278 6
279 6
        if ($results[0] != self::FSERV_STATUS_OK) {
280 6
            throw new GdaemonClientException('Couldn\'t move file: ' . (isset($results[1]) ? $results[1] : 'Unknown'));
281
        }
282 6
283 3
        return true;
284
    }
285
286 3
    public function copy(string $oldPath, string $newPath): bool
287
    {
288
        $message = $this->binn->serialize([
289
            self::FSERV_MOVE,
290
            $oldPath,
291
            $newPath,
292
            true           // Copy file
293
        ]);
294
295
        $read = $this->writeAndReadSocket($message);
296 9
297
        $results = $this->binn->unserialize($read);
298 9
299
        if ($results[0] != self::FSERV_STATUS_OK) {
300
            throw new GdaemonClientException('Couldn\'t copy file: ' . (isset($results[1]) ? $results[1] : 'Unknown'));
301
        }
302
303
        return true;
304
    }
305
306
    public function delete(string $path, bool $recursive = false): bool
307
    {
308 9
        $message = $this->binn->serialize([
309
            self::FSERV_REMOVE,
310 9
            $path,
311
            $recursive,
312 9
        ]);
313 9
314 9
        $read = $this->writeAndReadSocket($message);
315 9
316
        $results = $this->binn->unserialize($read);
317 9
318
        if ($results[0] != self::FSERV_STATUS_OK) {
319 9
            throw new GdaemonClientException('Couldn\'t delete: ' . (isset($results[1]) ? $results[1] : 'Unknown'));
320
        }
321 9
322 9
        return true;
323 9
    }
324
325 9
    public function metadata(string $path): array
326 3
    {
327
        $message = $this->binn->serialize([
328
            self::FSERV_FILEINFO,
329 6
            $path,
330
        ]);
331
332
        $read = $this->writeAndReadSocket($message);
333
334
        $results = $this->binn->unserialize($read);
335
336
        if ($results[0] != self::FSERV_STATUS_OK) {
337
            throw new GdaemonClientException('GDaemon metadata error: ' . (isset($results[1]) ? $results[1] : 'Unknown'));
338
        }
339 6
340
        $fileInfo = $results[2];
341 6
342
        return [
343 6
            'name' => basename($fileInfo[0]),
344 6
            'size' => $fileInfo[1],
345 6
            'type' => ($fileInfo[2] == 1) ? 'dir' : 'file',
346 6
            'mtime' => $fileInfo[3],
347
            'atime' => $fileInfo[4],
348 6
            'ctime' => $fileInfo[5],
349
            'permissions' => $fileInfo[6],
350 6
            'mimetype' => $fileInfo[7],
351 6
        ];
352 6
    }
353
354 6
    public function chmod(int $mode, string $path): bool
355 3
    {
356
        $message = $this->binn->serialize([
357
            self::FSERV_CHMOD,
358 3
            $path,
359
            $mode,
360
        ]);
361
362
        $read = $this->writeAndReadSocket($message);
363
364
        $results = $this->binn->unserialize($read);
365
366
        if ($results[0] != self::FSERV_STATUS_OK) {
367
            throw new GdaemonClientException('Couldn\'t chmod: ' . (isset($results[1]) ? $results[1] : 'Unknown'));
368 6
        }
369
370 6
        return true;
371
    }
372 6
373 6
    public function exist(string $path): bool
374 6
    {
375
        return in_array(basename($path), $this->listFiles(dirname($path)));
376 6
    }
377
}
378