Completed
Push — master ( 93822b...59ac94 )
by Nicolas
14s queued 11s
created

Local::deleteDirectory()   B

Complexity

Conditions 8
Paths 3

Size

Total Lines 32

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 32
rs 8.1635
c 0
b 0
f 0
cc 8
nc 3
nop 1
1
<?php
2
3
namespace Gaufrette\Adapter;
4
5
use Gaufrette\Util;
6
use Gaufrette\Adapter;
7
use Gaufrette\Stream;
8
9
10
/**
11
 * Adapter for the local filesystem.
12
 *
13
 * @author Antoine Hérault <[email protected]>
14
 * @author Leszek Prabucki <[email protected]>
15
 */
16
class Local implements Adapter,
17
    StreamFactory,
18
    ChecksumCalculator,
19
    SizeCalculator,
20
    MimeTypeProvider
21
{
22
    protected $directory;
23
    private $create;
24
    private $mode;
25
26
    /**
27
     * @param string $directory Directory where the filesystem is located
28
     * @param bool   $create    Whether to create the directory if it does not
29
     *                          exist (default FALSE)
30
     * @param int    $mode      Mode for mkdir
31
     *
32
     * @throws \RuntimeException if the specified directory does not exist and
33
     *                          could not be created
34
     */
35
    public function __construct($directory, $create = false, $mode = 0777)
36
    {
37
        $this->directory = Util\Path::normalize($directory);
38
39
        if (is_link($this->directory)) {
40
            $this->directory = realpath($this->directory);
41
        }
42
43
        $this->create = $create;
44
        $this->mode = $mode;
45
    }
46
47
    /**
48
     * {@inheritdoc}
49
     *
50
     * @throws \OutOfBoundsException     If the computed path is out of the directory
51
     * @throws \InvalidArgumentException if the directory already exists
52
     * @throws \RuntimeException         if the directory could not be created
53
     */
54
    public function read($key)
55
    {
56
        if ($this->isDirectory($key)) {
57
            return false;
58
        }
59
60
        return file_get_contents($this->computePath($key));
61
    }
62
63
    /**
64
     * {@inheritdoc}
65
     *
66
     * @throws \OutOfBoundsException     If the computed path is out of the directory
67
     * @throws \InvalidArgumentException if the directory already exists
68
     * @throws \RuntimeException         if the directory could not be created
69
     */
70 View Code Duplication
    public function write($key, $content)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
71
    {
72
        $path = $this->computePath($key);
73
        $this->ensureDirectoryExists(\Gaufrette\Util\Path::dirname($path), true);
74
75
        return file_put_contents($path, $content);
76
    }
77
78
    /**
79
     * {@inheritdoc}
80
     *
81
     * @throws \OutOfBoundsException     If the computed path is out of the directory
82
     * @throws \InvalidArgumentException if the directory already exists
83
     * @throws \RuntimeException         if the directory could not be created
84
     */
85 View Code Duplication
    public function rename($sourceKey, $targetKey)
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
86
    {
87
        $targetPath = $this->computePath($targetKey);
88
        $this->ensureDirectoryExists(\Gaufrette\Util\Path::dirname($targetPath), true);
89
90
        return rename($this->computePath($sourceKey), $targetPath);
91
    }
92
93
    /**
94
     * {@inheritdoc}
95
     */
96
    public function exists($key)
97
    {
98
        return is_file($this->computePath($key));
99
    }
100
101
    /**
102
     * {@inheritdoc}
103
     *
104
     * @throws \OutOfBoundsException     If the computed path is out of the directory
105
     * @throws \InvalidArgumentException if the directory already exists
106
     * @throws \RuntimeException         if the directory could not be created
107
     */
108
    public function keys()
109
    {
110
        $this->ensureDirectoryExists($this->directory, $this->create);
111
112
        try {
113
            $files = new \RecursiveIteratorIterator(
114
                new \RecursiveDirectoryIterator(
115
                    $this->directory,
116
                    \FilesystemIterator::SKIP_DOTS | \FilesystemIterator::UNIX_PATHS
117
                ),
118
                \RecursiveIteratorIterator::CHILD_FIRST
119
            );
120
        } catch (\Exception $e) {
121
            $files = new \EmptyIterator();
122
        }
123
124
        $keys = [];
125
        foreach ($files as $file) {
126
            $keys[] = $this->computeKey($file);
127
        }
128
        sort($keys);
129
130
        return $keys;
131
    }
132
133
    /**
134
     * {@inheritdoc}
135
     *
136
     * @throws \OutOfBoundsException     If the computed path is out of the directory
137
     * @throws \InvalidArgumentException if the directory already exists
138
     * @throws \RuntimeException         if the directory could not be created
139
     */
140
    public function mtime($key)
141
    {
142
        return filemtime($this->computePath($key));
143
    }
144
145
    /**
146
     * {@inheritdoc}
147
     *
148
     * Can also delete a directory recursively when the given $key matches a
149
     * directory.
150
     */
151
    public function delete($key)
152
    {
153
        if ($this->isDirectory($key)) {
154
            return $this->deleteDirectory($this->computePath($key));
155
        } elseif ($this->exists($key)) {
156
            return unlink($this->computePath($key));
157
        }
158
159
        return false;
160
    }
161
162
    /**
163
     * @param string $key
164
     *
165
     * @return bool
166
     *
167
     * @throws \OutOfBoundsException     If the computed path is out of the directory
168
     * @throws \InvalidArgumentException if the directory already exists
169
     * @throws \RuntimeException         if the directory could not be created
170
     */
171
    public function isDirectory($key)
172
    {
173
        return is_dir($this->computePath($key));
174
    }
175
176
    /**
177
     * {@inheritdoc}
178
     *
179
     * @throws \OutOfBoundsException     If the computed path is out of the directory
180
     * @throws \InvalidArgumentException if the directory already exists
181
     * @throws \RuntimeException         if the directory could not be created
182
     */
183
    public function createStream($key)
184
    {
185
        return new Stream\Local($this->computePath($key), $this->mode);
186
    }
187
188
    /**
189
     * {@inheritdoc}
190
     *
191
     * @throws \OutOfBoundsException     If the computed path is out of the directory
192
     * @throws \InvalidArgumentException if the directory already exists
193
     * @throws \RuntimeException         if the directory could not be created
194
     */
195
    public function checksum($key)
196
    {
197
        return Util\Checksum::fromFile($this->computePath($key));
198
    }
199
200
    /**
201
     * {@inheritdoc}
202
     *
203
     * @throws \OutOfBoundsException     If the computed path is out of the directory
204
     * @throws \InvalidArgumentException if the directory already exists
205
     * @throws \RuntimeException         if the directory could not be created
206
     */
207
    public function size($key)
208
    {
209
        return Util\Size::fromFile($this->computePath($key));
210
    }
211
212
    /**
213
     * {@inheritdoc}
214
     *
215
     * @throws \OutOfBoundsException     If the computed path is out of the directory
216
     * @throws \InvalidArgumentException if the directory already exists
217
     * @throws \RuntimeException         if the directory could not be created
218
     */
219
    public function mimeType($key)
220
    {
221
        $fileInfo = new \finfo(FILEINFO_MIME_TYPE);
222
223
        return $fileInfo->file($this->computePath($key));
224
    }
225
226
    /**
227
     * Computes the key from the specified path.
228
     *
229
     * @param $path
230
     * @return string
231
     *
232
     * @throws \OutOfBoundsException     If the computed path is out of the directory
233
     * @throws \InvalidArgumentException if the directory already exists
234
     * @throws \RuntimeException         if the directory could not be created
235
     */
236
    public function computeKey($path)
237
    {
238
        $path = $this->normalizePath($path);
239
240
        return ltrim(substr($path, strlen($this->directory)), '/');
241
    }
242
243
    /**
244
     * Computes the path from the specified key.
245
     *
246
     * @param string $key The key which for to compute the path
247
     *
248
     * @return string A path
249
     *
250
     * @throws \InvalidArgumentException If the directory already exists
251
     * @throws \OutOfBoundsException     If the computed path is out of the directory
252
     * @throws \RuntimeException         If directory does not exists and cannot be created
253
     */
254
    protected function computePath($key)
255
    {
256
        $this->ensureDirectoryExists($this->directory, $this->create);
257
258
        return $this->normalizePath($this->directory.'/'.$key);
259
    }
260
261
    /**
262
     * Normalizes the given path.
263
     *
264
     * @param string $path
265
     *
266
     * @return string
267
     * @throws \OutOfBoundsException If the computed path is out of the
268
     *                              directory
269
     */
270
    protected function normalizePath($path)
271
    {
272
        $path = Util\Path::normalize($path);
273
274
        if (0 !== strpos($path, $this->directory)) {
275
            throw new \OutOfBoundsException(sprintf('The path "%s" is out of the filesystem.', $path));
276
        }
277
278
        return $path;
279
    }
280
281
    /**
282
     * Ensures the specified directory exists, creates it if it does not.
283
     *
284
     * @param string $directory Path of the directory to test
285
     * @param bool   $create    Whether to create the directory if it does
286
     *                          not exist
287
     *
288
     * @throws \InvalidArgumentException if the directory already exists
289
     * @throws \RuntimeException if the directory does not exists and could not
290
     *                          be created
291
     */
292
    protected function ensureDirectoryExists($directory, $create = false)
293
    {
294
        if (!is_dir($directory)) {
295
            if (!$create) {
296
                throw new \RuntimeException(sprintf('The directory "%s" does not exist.', $directory));
297
            }
298
299
            $this->createDirectory($directory);
300
        }
301
    }
302
303
    /**
304
     * Creates the specified directory and its parents.
305
     *
306
     * @param string $directory Path of the directory to create
307
     *
308
     * @throws \InvalidArgumentException if the directory already exists
309
     * @throws \RuntimeException         if the directory could not be created
310
     */
311
    protected function createDirectory($directory)
312
    {
313
        if (!@mkdir($directory, $this->mode, true) && !is_dir($directory)) {
314
            throw new \RuntimeException(sprintf('The directory \'%s\' could not be created.', $directory));
315
        }
316
    }
317
318
    /**
319
     * @param string The directory's path to delete
320
     *
321
     * @throws \InvalidArgumentException When attempting to delete the root
322
     * directory of this adapter.
323
     *
324
     * @return bool Wheter the operation succeeded or not
325
     */
326
    private function deleteDirectory($directory)
327
    {
328
        if ($this->directory === $directory) {
329
            throw new \InvalidArgumentException(
330
                sprintf('Impossible to delete the root directory of this Local adapter ("%s").', $directory)
331
            );
332
        }
333
334
        $status = true;
335
336
        if (file_exists($directory)) {
337
            $iterator = new \RecursiveIteratorIterator(
338
                new \RecursiveDirectoryIterator(
339
                    $directory,
340
                    \FilesystemIterator::SKIP_DOTS | \FilesystemIterator::UNIX_PATHS
341
                ),
342
                \RecursiveIteratorIterator::CHILD_FIRST
343
            );
344
345
            foreach ($iterator as $item) {
346
                if ($item->isDir()) {
347
                    $status = $status && rmdir(strval($item));
348
                } else {
349
                    $status = $status && unlink(strval($item));
350
                }
351
            }
352
353
            $status = $status && rmdir($directory);
354
        }
355
356
        return $status;
357
    }
358
}
359