Completed
Push — master ( 95bf49...159bd4 )
by Hong
02:37
created

LocalDriver   B

Complexity

Total Complexity 40

Size/Duplication

Total Lines 311
Duplicated Lines 0 %

Coupling/Cohesion

Components 2
Dependencies 3

Importance

Changes 3
Bugs 0 Features 0
Metric Value
wmc 40
c 3
b 0
f 0
lcom 2
cbo 3
dl 0
loc 311
rs 8.2608

19 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 9 2
A realPath() 0 4 1
A realExists() 0 4 1
A isDir() 0 4 1
A readDir() 0 20 4
A openReadStream() 0 13 2
A readFile() 0 14 2
A getRealMeta() 0 19 2
A fixPath() 0 10 3
A writeStream() 0 13 3
A writeFile() 0 13 1
A setRealMeta() 0 13 3
A renameDir() 0 6 1
A renameFile() 0 6 1
A copyDir() 0 21 4
A copyFile() 0 6 1
A deleteDir() 0 19 4
A deleteFile() 0 4 1
A makeDirectory() 0 17 3

How to fix   Complexity   

Complex Class

Complex classes like LocalDriver 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. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.

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 LocalDriver, and based on these observations, apply Extract Interface, too.

1
<?php
2
/**
3
 * Phossa Project
4
 *
5
 * PHP version 5.4
6
 *
7
 * @category  Library
8
 * @package   Phossa2\Storage
9
 * @copyright Copyright (c) 2016 phossa.com
10
 * @license   http://mit-license.org/ MIT License
11
 * @link      http://www.phossa.com/
12
 */
13
/*# declare(strict_types=1); */
14
15
namespace Phossa2\Storage\Driver;
16
17
use Phossa2\Storage\Message\Message;
18
use Phossa2\Storage\Exception\LogicException;
19
20
/**
21
 * LocalDriver
22
 *
23
 * @package Phossa2\Storage
24
 * @author  Hong Zhang <[email protected]>
25
 * @see     DriverAbstract
26
 * @version 2.0.0
27
 * @since   2.0.0 added
28
 */
29
class LocalDriver extends DriverAbstract
30
{
31
    /**
32
     * driver root
33
     *
34
     * @var    string
35
     * @access protected
36
     */
37
    protected $root;
38
39
    /**
40
     * @param  string $rootDir
41
     * @throws LogicException
42
     * @access public
43
     */
44
    public function __construct(/*# string */ $rootDir)
45
    {
46
        if (!$this->makeDirectory($rootDir)) {
47
            throw new LogicException(
48
                $this->getError(), $this->getErrorCode()
49
            );
50
        }
51
        $this->root = rtrim($rootDir, "/\\") . \DIRECTORY_SEPARATOR;
52
    }
53
54
    /**
55
     * {@inheritDoc}
56
     */
57
    protected function realPath(/*# string */ $path)/*# : string */
58
    {
59
        return $this->root . str_replace('/', \DIRECTORY_SEPARATOR, $path);
60
    }
61
62
    /**
63
     * {@inheritDoc}
64
     */
65
    protected function realExists(/*# string */ $realPath)/*# : bool */
66
    {
67
        return file_exists($realPath);
68
    }
69
70
    /**
71
     * {@inheritDoc}
72
     */
73
    protected function isDir(/*# string */ $realPath)/*# : bool */
74
    {
75
        return is_dir($realPath);
76
    }
77
78
    /**
79
     * {@inheritDoc}
80
     */
81
    protected function readDir(
82
        /*# string */ $realPath,
83
        /*# string */ $prefix = ''
84
    )/*# : array */ {
85
        try {
86
            $res = [];
87
            foreach (new \DirectoryIterator($realPath) as $fileInfo) {
88
                if($fileInfo->isDot()) continue;
89
                $res[] = $prefix . $fileInfo->getFilename();
90
            }
91
            return $res;
92
93
        } catch (\Exception $e) {
94
            $this->setError(
95
                Message::get(Message::STR_READDIR_FAIL, $realPath),
96
                Message::STR_READDIR_FAIL
97
            );
98
            return [];
99
        }
100
    }
101
102
    /**
103
     * {@inheritDoc}
104
     */
105
    protected function openReadStream(/*# string */ $realPath)
106
    {
107
        $stream = fopen($realPath, 'r');
108
        if (is_resource($stream)) {
109
            return $stream;
110
        } else {
111
            $this->setError(
112
                Message::get(Message::STR_OPENSTREAM_FAIL, $realPath),
113
                Message::STR_OPENSTREAM_FAIL
114
            );
115
            return null;
116
        }
117
    }
118
119
    /**
120
     * {@inheritDoc}
121
     */
122
    protected function readFile(/*# string */ $realPath)
123
    {
124
        $str = file_get_contents($realPath);
125
126
        if (false === $str) {
127
            $this->setError(
128
                Message::get(Message::STR_OPENSTREAM_FAIL, $realPath),
129
                Message::STR_OPENSTREAM_FAIL
130
            );
131
            return null;
132
        }
133
134
        return $str;
135
    }
136
137
    /**
138
     * {@inheritDoc}
139
     */
140
    protected function getRealMeta(/*# string */ $realPath)/*# : array */
141
    {
142
        try {
143
            $info = new \SplFileInfo($realPath);
144
            return [
145
                'type'  => $info->getType(),
146
                'size'  => $info->getSize(),
147
                'perm'  => $info->getPerms(),
148
                'ctime' => $info->getCTime(),
149
                'mtime' => $info->getMTime(),
150
            ];
151
        } catch (\Exception $e) {
152
            $this->setError(
153
                Message::get(Message::STR_GETMETA_FAIL, $realPath),
154
                Message::STR_GETMETA_FAIL
155
            );
156
            return [];
157
        }
158
    }
159
160
    /**
161
     * {@inheritDoc}
162
     */
163
    protected function fixPath()/*# : bool */
164
    {
165
        foreach (func_get_args() as $realPath) {
166
            $parent = dirname($realPath);
167
            if (!$this->makeDirectory($parent)) {
168
                return false;
169
            }
170
        }
171
        return true;
172
    }
173
174
    /**
175
     * {@inheritDoc}
176
     */
177
    protected function writeStream(
178
        /*# string */ $realPath,
179
        $resource
180
    )/*# : bool */ {
181
        $tmpfname = tempnam(dirname($realPath), 'FOO');
182
        $stream = fopen($tmpfname, 'w+b');
183
184
        if (is_resource($stream)) {
185
            stream_copy_to_stream($resource, $stream);
186
            return fclose($stream) && rename($tmpfname, $realPath);
187
        }
188
        return false;
189
    }
190
191
    /**
192
     * {@inheritDoc}
193
     */
194
    protected function writeFile(
195
        /*# string */ $realPath,
196
        /*# string */ $content
197
    )/*# : bool */ {
198
        // write to a temp file
199
        $tmpfname = tempnam(dirname($realPath), 'FOO');
200
        $handle = fopen($tmpfname, 'w');
201
        fwrite($handle, $content);
202
        fclose($handle);
203
204
        // rename to $realPath
205
        return rename($tmpfname, $realPath);
206
    }
207
208
    /**
209
     * Write meta data
210
     *
211
     * @param  string $realPath
212
     * @param  array $meta
213
     * @return bool
214
     * @access protected
215
     */
216
    protected function setRealMeta(
217
        /*# string */ $realPath,
218
        array $meta
219
    )/*# : bool */ {
220
        if (isset($meta['mtime'])) {
221
            touch($realPath, $meta['mtime']);
222
        }
223
224
        if (isset($meta['perm'])) {
225
            chmod($realPath, (int) $meta['perm']);
226
        }
227
        return true;
228
    }
229
230
    /**
231
     * {@inheritDoc}
232
     */
233
    protected function renameDir(
234
        /*# string */ $from,
235
        /*# string */ $to
236
    )/*# : bool */ {
237
        return rename($from, $to);
238
    }
239
240
    /**
241
     * {@inheritDoc}
242
     */
243
    protected function renameFile(
244
        /*# string */ $from,
245
        /*# string */ $to
246
    )/*# : bool */ {
247
        return rename($from, $to);
248
    }
249
250
    /**
251
     * {@inheritDoc}
252
     */
253
    protected function copyDir(
254
        /*# string */ $from,
255
        /*# string */ $to
256
    )/*# : bool */ {
257
        $files = $this->readDir($from);
258
259
        foreach ($files as $file) {
260
            $f = $from . \DIRECTORY_SEPARATOR . $file;
261
            $t = $to . \DIRECTORY_SEPARATOR . $file;
262
            if (is_dir($f)) {
263
                $this->makeDirectory($t);
264
                $res = $this->copyDir($f, $t);
265
            } else {
266
                $res = $this->copyFile($f, $t);
267
            }
268
            if (false === $res) {
269
                return false;
270
            }
271
        }
272
        return true;
273
    }
274
275
    /**
276
     * {@inheritDoc}
277
     */
278
    protected function copyFile(
279
        /*# string */ $from,
280
        /*# string */ $to
281
    )/*# : bool */ {
282
        return copy($from, $to);
283
    }
284
285
    /**
286
     * {@inheritDoc}
287
     */
288
    protected function deleteDir(/*# string */ $realPath)/*# : bool */
289
    {
290
        $files = $this->readDir($realPath, $realPath);
291
292
        foreach ($files as $file) {
293
            if (is_dir($file)) {
294
                $res = $this->deleteDir($file);
295
            } else {
296
                $res = unlink($file);
297
            }
298
            if (false === $res) {
299
                return $this->setError(
300
                    Message::get(Message::STR_DELETE_FAIL, $file),
301
                    Message::STR_DELETE_FAIL
302
                );
303
            }
304
        }
305
        return rmdir($realPath);
306
    }
307
308
    /**
309
     * {@inheritDoc}
310
     */
311
    protected function deleteFile(/*# string */ $realPath)/*# : bool */
312
    {
313
        return unlink($realPath);
314
    }
315
316
    /**
317
     * create directory
318
     *
319
     * @param  string $dir
320
     * @access protected
321
     */
322
    protected function makeDirectory(/*# string */ $dir)/*# : bool */
323
    {
324
        if (!is_dir($dir)) {
325
            $umask = umask(0);
326
            mkdir($dir, 0755, true);
327
            umask($umask);
328
329
            if (!is_dir($dir)) {
330
                $this->setError(
331
                    Message::get(Message::STR_MKDIR_FAIL, $dir),
332
                    Message::STR_MKDIR_FAIL
333
                );
334
                return false;
335
            }
336
        }
337
        return true;
338
    }
339
}
340