Completed
Push — master ( 159bd4...9ef354 )
by Hong
02:36
created

LocalDriver   B

Complexity

Total Complexity 40

Size/Duplication

Total Lines 309
Duplicated Lines 0 %

Coupling/Cohesion

Components 2
Dependencies 3

Importance

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

19 Methods

Rating   Name   Duplication   Size   Complexity  
A __construct() 0 9 2
A realPath() 0 5 2
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 18 2
A ensurePath() 0 8 2
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 . ('/' !== \DIRECTORY_SEPARATOR ?
60
            str_replace('/', \DIRECTORY_SEPARATOR, $path) : $path);
61
    }
62
63
    /**
64
     * {@inheritDoc}
65
     */
66
    protected function realExists(/*# string */ $realPath)/*# : bool */
67
    {
68
        return file_exists($realPath);
69
    }
70
71
    /**
72
     * {@inheritDoc}
73
     */
74
    protected function isDir(/*# string */ $realPath)/*# : bool */
75
    {
76
        return is_dir($realPath);
77
    }
78
79
    /**
80
     * {@inheritDoc}
81
     */
82
    protected function readDir(
83
        /*# string */ $realPath,
84
        /*# string */ $prefix = ''
85
    )/*# : array */ {
86
        try {
87
            $res = [];
88
            foreach (new \DirectoryIterator($realPath) as $fileInfo) {
89
                if($fileInfo->isDot()) continue;
90
                $res[] = $prefix . $fileInfo->getFilename();
91
            }
92
            return $res;
93
94
        } catch (\Exception $e) {
95
            $this->setError(
96
                Message::get(Message::STR_READDIR_FAIL, $realPath),
97
                Message::STR_READDIR_FAIL
98
            );
99
            return [];
100
        }
101
    }
102
103
    /**
104
     * {@inheritDoc}
105
     */
106
    protected function openReadStream(/*# string */ $realPath)
107
    {
108
        $stream = fopen($realPath, 'r');
109
        if (is_resource($stream)) {
110
            return $stream;
111
        } else {
112
            $this->setError(
113
                Message::get(Message::STR_OPENSTREAM_FAIL, $realPath),
114
                Message::STR_OPENSTREAM_FAIL
115
            );
116
            return null;
117
        }
118
    }
119
120
    /**
121
     * {@inheritDoc}
122
     */
123
    protected function readFile(/*# string */ $realPath)
124
    {
125
        $str = file_get_contents($realPath);
126
127
        if (false === $str) {
128
            $this->setError(
129
                Message::get(Message::STR_OPENSTREAM_FAIL, $realPath),
130
                Message::STR_OPENSTREAM_FAIL
131
            );
132
            return null;
133
        }
134
135
        return $str;
136
    }
137
138
    /**
139
     * {@inheritDoc}
140
     */
141
    protected function getRealMeta(/*# string */ $realPath)/*# : array */
142
    {
143
        try {
144
            $info = new \SplFileInfo($realPath);
145
            return [
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 ensurePath(/*# string */ $realPath)/*# : bool */
164
    {
165
        $parent = dirname($realPath);
166
        if (!$this->makeDirectory($parent)) {
167
            return false;
168
        }
169
        return true;
170
    }
171
172
    /**
173
     * {@inheritDoc}
174
     */
175
    protected function writeStream(
176
        /*# string */ $realPath,
177
        $resource
178
    )/*# : bool */ {
179
        $tmpfname = tempnam(dirname($realPath), 'FOO');
180
        $stream = fopen($tmpfname, 'w+b');
181
182
        if (is_resource($stream)) {
183
            stream_copy_to_stream($resource, $stream);
184
            return fclose($stream) && rename($tmpfname, $realPath);
185
        }
186
        return false;
187
    }
188
189
    /**
190
     * {@inheritDoc}
191
     */
192
    protected function writeFile(
193
        /*# string */ $realPath,
194
        /*# string */ $content
195
    )/*# : bool */ {
196
        // write to a temp file
197
        $tmpfname = tempnam(dirname($realPath), 'FOO');
198
        $handle = fopen($tmpfname, 'w');
199
        fwrite($handle, $content);
200
        fclose($handle);
201
202
        // rename to $realPath
203
        return rename($tmpfname, $realPath);
204
    }
205
206
    /**
207
     * Write meta data
208
     *
209
     * @param  string $realPath
210
     * @param  array $meta
211
     * @return bool
212
     * @access protected
213
     */
214
    protected function setRealMeta(
215
        /*# string */ $realPath,
216
        array $meta
217
    )/*# : bool */ {
218
        if (isset($meta['mtime'])) {
219
            touch($realPath, $meta['mtime']);
220
        }
221
222
        if (isset($meta['perm'])) {
223
            chmod($realPath, (int) $meta['perm']);
224
        }
225
        return true;
226
    }
227
228
    /**
229
     * {@inheritDoc}
230
     */
231
    protected function renameDir(
232
        /*# string */ $from,
233
        /*# string */ $to
234
    )/*# : bool */ {
235
        return rename($from, $to);
236
    }
237
238
    /**
239
     * {@inheritDoc}
240
     */
241
    protected function renameFile(
242
        /*# string */ $from,
243
        /*# string */ $to
244
    )/*# : bool */ {
245
        return rename($from, $to);
246
    }
247
248
    /**
249
     * {@inheritDoc}
250
     */
251
    protected function copyDir(
252
        /*# string */ $from,
253
        /*# string */ $to
254
    )/*# : bool */ {
255
        $files = $this->readDir($from);
256
257
        foreach ($files as $file) {
258
            $f = $from . \DIRECTORY_SEPARATOR . $file;
259
            $t = $to . \DIRECTORY_SEPARATOR . $file;
260
            if (is_dir($f)) {
261
                $this->makeDirectory($t);
262
                $res = $this->copyDir($f, $t);
263
            } else {
264
                $res = $this->copyFile($f, $t);
265
            }
266
            if (false === $res) {
267
                return false;
268
            }
269
        }
270
        return true;
271
    }
272
273
    /**
274
     * {@inheritDoc}
275
     */
276
    protected function copyFile(
277
        /*# string */ $from,
278
        /*# string */ $to
279
    )/*# : bool */ {
280
        return copy($from, $to);
281
    }
282
283
    /**
284
     * {@inheritDoc}
285
     */
286
    protected function deleteDir(/*# string */ $realPath)/*# : bool */
287
    {
288
        $files = $this->readDir($realPath, $realPath);
289
290
        foreach ($files as $file) {
291
            if (is_dir($file)) {
292
                $res = $this->deleteDir($file);
293
            } else {
294
                $res = unlink($file);
295
            }
296
            if (false === $res) {
297
                return $this->setError(
298
                    Message::get(Message::STR_DELETE_FAIL, $file),
299
                    Message::STR_DELETE_FAIL
300
                );
301
            }
302
        }
303
        return rmdir($realPath);
304
    }
305
306
    /**
307
     * {@inheritDoc}
308
     */
309
    protected function deleteFile(/*# string */ $realPath)/*# : bool */
310
    {
311
        return unlink($realPath);
312
    }
313
314
    /**
315
     * create directory
316
     *
317
     * @param  string $dir
318
     * @access protected
319
     */
320
    protected function makeDirectory(/*# string */ $dir)/*# : bool */
321
    {
322
        if (!is_dir($dir)) {
323
            $umask = umask(0);
324
            mkdir($dir, 0755, true);
325
            umask($umask);
326
327
            if (!is_dir($dir)) {
328
                $this->setError(
329
                    Message::get(Message::STR_MKDIR_FAIL, $dir),
330
                    Message::STR_MKDIR_FAIL
331
                );
332
                return false;
333
            }
334
        }
335
        return true;
336
    }
337
}
338