Passed
Push — master ( 304f84...5965ff )
by Nikita
02:10
created

GdaemonFiles   C

Complexity

Total Complexity 53

Size/Duplication

Total Lines 455
Duplicated Lines 0 %

Test Coverage

Coverage 99.05%

Importance

Changes 2
Bugs 0 Features 0
Metric Value
eloc 214
c 2
b 0
f 0
dl 0
loc 455
ccs 208
cts 210
cp 0.9905
rs 6.96
wmc 53

12 Methods

Rating   Name   Duplication   Size   Complexity  
A move() 0 22 3
A delete() 0 19 3
A metadata() 0 29 4
A chmod() 0 19 3
B get() 0 58 10
A rename() 0 3 1
A listFiles() 0 33 5
A mkdir() 0 19 3
A copy() 0 20 3
A exist() 0 3 1
B directoryContents() 0 38 6
B put() 0 61 11

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\Binn\BinnList;
6
use RuntimeException;
7
use InvalidArgumentException;
8
9
class GdaemonFiles extends Gdaemon
10
{
11
    const FSERV_AUTH            = 1;
12
    const FSERV_FILESEND        = 3;
13
    const FSERV_READDIR         = 4;
14
    const FSERV_MKDIR           = 5;
15
    const FSERV_MOVE            = 6;
16
    const FSERV_REMOVE          = 7;
17
    const FSERV_FILEINFO        = 8;
18
    const FSERV_CHMOD           = 9;
19
20
    const FSERV_UPLOAD_TO_SERVER        = 1;
21
    const FSERV_DOWNLOAD_FR_SERVER      = 2;
22
23
    const FSERV_STATUS_ERROR                = 1;
24
    const FSERV_STATUS_UNKNOWN_COMMAND      = 3;
25
    const FSERV_STATUS_OK                   = 100;
26
    const FSERV_STATUS_FILE_TRANSFER_READY  = 101;
27
28
    /**
29
     * @var int
30
     */
31
    protected $mode = self::DAEMON_SERVER_MODE_FILES;
32
33
    /**
34
     * Upload file to server
35
     *
36
     * @param string|resource $locFile path to local file or file stream
37
     * @param string $remFile path to remote file
38
     * @param int $permission
39
     *
40
     * @return bool|resource
41
     */
42 21
    public function put($locFile, $remFile, $permission = 0644)
43
    {
44 21
        if (is_string($locFile)) {
45
            set_error_handler(function () {});
46 15
            $fileHandle = fopen($locFile, 'r');
47 15
            restore_error_handler();
48 11
        } else if (is_resource($locFile)) {
49 3
            $fileHandle = $locFile;
50 1
        } else {
51 3
            throw new InvalidArgumentException('Invalid local file');
52
        }
53
54 18
        if ($fileHandle === false) {
55 3
            throw new RuntimeException('File open error');
56
        }
57
58 15
        $stat = fstat($fileHandle);
59 15
        $filesize = $stat['size'];
60 15
        unset($stat);
61
62 15
        $writeBinn = new BinnList;
63
64 15
        $writeBinn->addUint8(self::FSERV_FILESEND);
65 15
        $writeBinn->addUint8(self::FSERV_UPLOAD_TO_SERVER);
66 15
        $writeBinn->addStr($remFile);
67 15
        $writeBinn->addUint64($filesize);
68 15
        $writeBinn->addBool(true); // Make dirs
69 15
        $writeBinn->addUint8($permission);
70
71 15
        $read = $this->writeAndReadSocket($writeBinn->serialize());
72
73 15
        $readBinn = new BinnList;
74 15
        $readBinn->binnOpen($read);
75 15
        $results = $readBinn->unserialize();
76
77 15
        if ($results[0] == self::FSERV_STATUS_OK) {
78 3
            throw new RuntimeException('Unexpected \'OK\' status. Expected \'ready to transfer\'');
79 12
        } else if ($results[0] != self::FSERV_STATUS_FILE_TRANSFER_READY) {
80 3
            throw new RuntimeException('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
89 9
        $readBinn = new BinnList;
90 9
        $readBinn->binnOpen($read);
91 9
        $results = $readBinn->unserialize();
92
93 9
        if ($results[0] != self::FSERV_STATUS_OK) {
94 3
            throw new RuntimeException('Couldn\'t send file: ' . (isset($results[1]) ? $results[1] : 'Unknown'));
95
        }
96
97 6
        if (is_resource($locFile)) {
98 3
            rewind($fileHandle);
99 3
            return $fileHandle;
100
        } else {
101 3
            fclose($fileHandle);
102 3
            return true;
103
        }
104
    }
105
106
    /**
107
     * Download file
108
     *
109
     * @param string $remFile path to remote file
110
     * @param string|resource $locFile path to local file or file stream
111
     *
112
     * @return boolean|resource
113
     */
114 24
    public function get($remFile, $locFile)
115
    {
116 24
        if (is_string($locFile)) {
117
            set_error_handler(function () {});
118 18
            $fileHandle = fopen($locFile, 'w+b');
119 18
            restore_error_handler();
120 12
        } else if (is_resource($locFile)) {
121 3
            $fileHandle = $locFile;
122 1
        } else {
123 3
            throw new InvalidArgumentException('Invalid local file');
124
        }
125
126 21
        if ($fileHandle === false) {
127 3
            throw new RuntimeException('File open error');
128
        }
129
130 18
        $writeBinn = new BinnList;
131
132 18
        $writeBinn->addUint8(self::FSERV_FILESEND);
133 18
        $writeBinn->addUint8(self::FSERV_DOWNLOAD_FR_SERVER);
134 18
        $writeBinn->addStr($remFile);
135
136 18
        $read = $this->writeAndReadSocket($writeBinn->serialize());
137
138 18
        $readBinn = new BinnList;
139 18
        $readBinn->binnOpen($read);
140 18
        $results = $readBinn->unserialize();
141
142 18
        if ($results[0] == self::FSERV_STATUS_OK) {
143 3
            throw new RuntimeException('Unexpected `OK` status. Expected `ready to transfer`');
144 15
        } else if ($results[0] != self::FSERV_STATUS_FILE_TRANSFER_READY) {
145 3
            throw new RuntimeException('Couldn\'t upload file: ' . (isset($results[1]) ? $results[1] : 'Unknown'));
146
        }
147
148 12
        $this->writeSocket(self::SOCKET_MSG_ENDL);
149
150 12
        $filesize = $results[2];
151 12
        $writed = 0;
152
153 12
        while($writed < $filesize) {
154 12
            if ($filesize - $writed > $this->maxBufsize) {
155 3
                $readlen = $this->maxBufsize;
156 1
            }
157
            else {
158 12
                $readlen = $filesize - $writed;
159
            }
160
161 12
            $socketRead = $this->readSocket($readlen, true);
162
163 12
            $writed += fwrite($fileHandle, $socketRead, $readlen);
164 4
        }
165
166 12
        if (is_resource($locFile)) {
167 3
            rewind($fileHandle);
168 3
            return $fileHandle;
169
        } else {
170 9
            fclose($fileHandle);
171 9
            return true;
172
        }
173
    }
174
175
    /**
176
     * List files
177
     *
178
     * @param string $directory
179
     *
180
     * @return array Files names list
181
     */
182 12
    public function listFiles($directory)
183
    {
184 12
        $writeBinn= new BinnList;
185
186 12
        $writeBinn->addUint8(self::FSERV_READDIR);
187 12
        $writeBinn->addStr($directory);     // Dir path
188 12
        $writeBinn->addUint8(0);       // Mode
189
190 12
        $read = $this->writeAndReadSocket($writeBinn->serialize());
191
192 12
        $readBinn = new BinnList;
193
194 12
        $readBinn->binnOpen($read);
195 12
        $results = $readBinn->unserialize();
196
197 12
        if ($results[0] != self::FSERV_STATUS_OK) {
198
            // Error
199 3
            throw new RuntimeException('GDaemon List files error:' . (isset($results[1]) ? $results[1] : 'Unknown'));
200
        }
201
202 9
        $filesList = $results[2];
203 9
        $returnList = [];
204
205 9
        foreach($filesList as &$file) {
206
207 9
            if (in_array(basename($file[0]), ['.', '..'])) {
208 3
                continue;
209
            }
210
211 9
            $returnList[] = basename($file[0]);
212 3
        }
213
214 9
        return $returnList;
215
    }
216
217
    /**
218
     * @param string $directory
219
     * @return array
220
     */
221 9
    public function directoryContents($directory)
222
    {
223 9
        $writeBinn= new BinnList;
224
225 9
        $writeBinn->addUint8(self::FSERV_READDIR);
226 9
        $writeBinn->addStr($directory);     // Dir path
227 9
        $writeBinn->addUint8(1);       // Mode
228
229 9
        $read = $this->writeAndReadSocket($writeBinn->serialize());
230
231 9
        $readBinn = new BinnList;
232
233 9
        $readBinn->binnOpen($read);
234 9
        $results = $readBinn->unserialize();
235
236 9
        if ($results[0] != self::FSERV_STATUS_OK) {
237
            // Error
238 3
            throw new RuntimeException('GDaemon List files error:' . (isset($results[1]) ? $results[1] : 'Unknown'));
239
        }
240
241 6
        $filesList = $results[2];
242 6
        $returnList = [];
243
244 6
        foreach($filesList as &$file) {
245 3
            if (in_array(basename($file[0]), ['.', '..'])) {
246 3
                continue;
247
            }
248
249 3
            $returnList[] = array(
250 3
                'name' => basename($file[0]),
251 3
                'size' => $file[1],
252 3
                'mtime' => $file[2],
253 3
                'type' => ($file[3] == 1) ? 'dir' : 'file',
254 3
                'permissions' => $file[4],
255
            );
256 2
        }
257
258 6
        return $returnList;
259
    }
260
261
    /**
262
     * Make directory
263
     *
264
     * @param string $path
265
     * @param int $permissions
266
     * @return bool
267
     */
268 6
    public function mkdir($path, $permissions = 0755)
269
    {
270 6
        $writeBinn = new BinnList;
271
272 6
        $writeBinn->addUint8(self::FSERV_MKDIR);
273 6
        $writeBinn->addStr($path);
274 6
        $writeBinn->addStr($permissions);
275
276 6
        $read = $this->writeAndReadSocket($writeBinn->serialize());
277
278 6
        $readBinn = new BinnList;
279 6
        $readBinn->binnOpen($read);
280 6
        $results = $readBinn->unserialize();
281
282 6
        if ($results[0] != self::FSERV_STATUS_OK) {
283 3
            throw new RuntimeException('Couldn\'t make directory: ' . isset($results[1]) ? $results[1] : 'Unknown');
284
        }
285
286 3
        return true;
287
    }
288
289
    /**
290
     * Rename file
291
     *
292
     * @param string $oldPath
293
     * @param string $newPath
294
     * @return bool
295
     */
296 9
    public function rename($oldPath, $newPath)
297
    {
298 9
        return $this->move($oldPath, $newPath);
299
    }
300
301
    /**
302
     * Move file
303
     *
304
     * @param string $oldPath
305
     * @param string $newPath
306
     * @return bool
307
     */
308 9
    public function move($oldPath, $newPath)
309
    {
310 9
        $writeBinn = new BinnList;
311
312 9
        $writeBinn->addUint8(self::FSERV_MOVE);
313 9
        $writeBinn->addStr($oldPath);
314 9
        $writeBinn->addStr($newPath);
315 9
        $writeBinn->addBool(false);
316
317 9
        $binn = $writeBinn->serialize();
318
319 9
        $read = $this->writeAndReadSocket($binn);
320
321 9
        $readBinn = new BinnList;
322 9
        $readBinn->binnOpen($read);
323 9
        $results = $readBinn->unserialize();
324
325 9
        if ($results[0] != self::FSERV_STATUS_OK) {
326 3
            throw new RuntimeException('Couldn\'t move file: ' . (isset($results[1]) ? $results[1] : 'Unknown'));
327
        }
328
329 6
        return true;
330
    }
331
332
    /**
333
     * Copy file
334
     *
335
     * @param string $oldPath
336
     * @param string $newPath
337
     * @return bool
338
     */
339 6
    public function copy($oldPath, $newPath)
340
    {
341 6
        $writeBinn = new BinnList;
342
343 6
        $writeBinn->addUint8(self::FSERV_MOVE);
344 6
        $writeBinn->addStr($oldPath);
345 6
        $writeBinn->addStr($newPath);
346 6
        $writeBinn->addBool(true);            // Copy
347
348 6
        $read = $this->writeAndReadSocket($writeBinn->serialize());
349
350 6
        $readBinn = new BinnList;
351 6
        $readBinn->binnOpen($read);
352 6
        $results = $readBinn->unserialize();
353
354 6
        if ($results[0] != self::FSERV_STATUS_OK) {
355 3
            throw new RuntimeException('Couldn\'t copy file: ' . (isset($results[1]) ? $results[1] : 'Unknown'));
356
        }
357
358 3
        return true;
359
    }
360
361
    /**
362
     * Delete file/directory
363
     *
364
     * @param string $path
365
     * @param bool $recursive
366
     * @return bool
367
     */
368 6
    public function delete($path, $recursive = false)
369
    {
370 6
        $writeBinn = new BinnList;
371
372 6
        $writeBinn->addUint8(self::FSERV_REMOVE);
373 6
        $writeBinn->addStr($path);
374 6
        $writeBinn->addBool($recursive);
375
376 6
        $read = $this->writeAndReadSocket($writeBinn->serialize());
377
378 6
        $readBinn = new BinnList;
379 6
        $readBinn->binnOpen($read);
380 6
        $results = $readBinn->unserialize();
381
382 6
        if ($results[0] != self::FSERV_STATUS_OK) {
383 3
            throw new RuntimeException('Couldn\'t delete: ' . (isset($results[1]) ? $results[1] : 'Unknown'));
384
        }
385
386 3
        return true;
387
    }
388
389
    /**
390
     * Get file metadata
391
     *
392
     * @param string $path
393
     * @return array
394
     */
395 6
    public function metadata($path)
396
    {
397 6
        $writeBinn= new BinnList;
398
399 6
        $writeBinn->addUint8(self::FSERV_FILEINFO);
400 6
        $writeBinn->addStr($path);
401
402 6
        $read = $this->writeAndReadSocket($writeBinn->serialize());
403
404 6
        $readBinn = new BinnList;
405
406 6
        $readBinn->binnOpen($read);
407 6
        $results = $readBinn->unserialize();
408
409 6
        if ($results[0] != self::FSERV_STATUS_OK) {
410 3
            throw new RuntimeException('GDaemon metadata error: ' . (isset($results[1]) ? $results[1] : 'Unknown'));
411
        }
412
413 3
        $fileInfo = $results[2];
414
415
        return [
416 3
            'name' => basename($fileInfo[0]),
417 3
            'size' => $fileInfo[1],
418 3
            'type' => ($fileInfo[2] == 1) ? 'dir' : 'file',
419 3
            'mtime' => $fileInfo[3],
420 3
            'atime' => $fileInfo[4],
421 3
            'ctime' => $fileInfo[5],
422 3
            'permissions' => $fileInfo[6],
423 3
            'mimetype' => $fileInfo[7],
424 1
        ];
425
    }
426
427
    /**
428
     * Change file mode
429
     *
430
     * @param integer $mode
431
     * @param string $path
432
     * @return bool
433
     */
434 6
    public function chmod($mode, $path)
435
    {
436 6
        $writeBinn = new BinnList;
437
438 6
        $writeBinn->addUint8(self::FSERV_CHMOD);
439 6
        $writeBinn->addStr($path);
440 6
        $writeBinn->addUint16($mode);
441
442 6
        $read = $this->writeAndReadSocket($writeBinn->serialize());
443
444 6
        $readBinn = new BinnList;
445 6
        $readBinn->binnOpen($read);
446 6
        $results = $readBinn->unserialize();
447
448 6
        if ($results[0] != self::FSERV_STATUS_OK) {
449 3
            throw new RuntimeException('Couldn\'t chmod: ' . (isset($results[1]) ? $results[1] : 'Unknown'));
450
        }
451
452 3
        return true;
453
    }
454
455
    /**
456
     * Check file exist
457
     *
458
     * @param $path
459
     * @return bool
460
     */
461 6
    public function exist($path)
462
    {
463 6
        return in_array(basename($path), $this->listFiles(dirname($path)));
464
    }
465
}