NativeFileSystem::exists()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 4
Code Lines 2

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
c 1
b 0
f 0
dl 0
loc 4
rs 10
cc 1
eloc 2
nc 1
nop 1
1
<?php
2
3
/**
4
 * Author: Nil Portugués Calderó <[email protected]>
5
 * Date: 6/02/16
6
 * Time: 14:03.
7
 *
8
 * For the full copyright and license information, please view the LICENSE
9
 * file that was distributed with this source code.
10
 */
11
namespace NilPortugues\Foundation\Infrastructure\Model\Repository\FileSystem\Drivers;
12
13
use NilPortugues\Foundation\Infrastructure\Model\Repository\FileSystem\Contracts\FileSystem;
14
use RuntimeException;
15
16
/**
17
 * Class NativeFileSystem.
18
 */
19
class NativeFileSystem implements FileSystem
20
{
21
    const EXTENSION = '.dbdata';
22
23
    /**
24
     * @var string
25
     */
26
    private $baseDir;
27
28
    /**
29
     * NativeFileSystem constructor.
30
     *
31
     * @param $baseDir
32
     */
33
    public function __construct($baseDir)
34
    {
35
        $this->baseDir = realpath($baseDir);
36
37
        if (false === file_exists($this->baseDir)) {
38
            throw new RuntimeException(
39
               sprintf('Provided base directory \'%s\' does not exist', $baseDir)
40
           );
41
        }
42
    }
43
44
    /**
45
     * Reads a file from the file system.
46
     *
47
     * @param string $filePath
48
     *
49
     * @return mixed
50
     */
51
    public function read($filePath)
52
    {
53
        $filePath = $this->calculateFilePath($filePath);
54
55
        if (false === file_exists($filePath)) {
56
            return;
57
        }
58
59
        return unserialize(file_get_contents($filePath));
60
    }
61
62
    /**
63
     * @param $id
64
     *
65
     * @return string
66
     */
67
    private function calculateFilePath($id)
68
    {
69
        return $this->baseDir()
70
        .DIRECTORY_SEPARATOR
71
        .$this->getDirectoryHash($id)
72
        .DIRECTORY_SEPARATOR
73
        .$id
74
        .self::EXTENSION;
75
    }
76
77
    /**
78
     * Returns the base directory.
79
     *
80
     * @return string
81
     */
82
    public function baseDir()
83
    {
84
        return $this->baseDir;
85
    }
86
87
    /**
88
     * @param string $key
89
     *
90
     * @return string
91
     */
92
    private function getDirectoryHash($key)
93
    {
94
        $key = \md5($key);
95
        $level1 = \substr($key, 0, 1);
96
        $level2 = \substr($key, 1, 1);
97
        $level3 = \substr($key, 2, 1);
98
        $directoryHash = $level1.DIRECTORY_SEPARATOR.$level2.DIRECTORY_SEPARATOR.$level3;
99
100
        return $directoryHash;
101
    }
102
103
    /**
104
     * Writes a file to the file system.
105
     *
106
     * @param string $filePath
107
     * @param string $contents
108
     *
109
     * @return bool
110
     */
111
    public function write($filePath, $contents)
112
    {
113
        $this->createDirectory($this->getDirectoryHash($filePath));
114
        $filePath = $this->calculateFilePath($filePath);
115
116
        return false !== file_put_contents($filePath, serialize($contents), FILE_APPEND | LOCK_EX);
117
    }
118
119
    /**
120
     * @param $filePath
121
     */
122
    private function createDirectory($filePath)
123
    {
124
        $filePath = $this->baseDir().DIRECTORY_SEPARATOR.$filePath;
125
126
        if (false === file_exists($filePath)) {
127
            mkdir($filePath, 0755, true);
128
        }
129
    }
130
131
    /**
132
     * Returns a flat array containing a list of files in a directory.
133
     * Files are searched recursively.
134
     *
135
     * @return array
136
     */
137
    public function files()
138
    {
139
        $files = [];
140
        $directory = $this->baseDir();
141
        $this->filesRecursively($directory, $files);
142
143
        return $files;
144
    }
145
146
    /**
147
     * @param string $directory
148
     * @param array  $files
149
     */
150
    private function filesRecursively($directory, array &$files)
151
    {
152
        foreach (glob("{$directory}/*") as $file) {
153
            if (\is_dir($file)) {
154
                $this->filesRecursively($file, $files);
155
            } else {
156
                $files[] = unserialize(file_get_contents($file));
157
            }
158
        }
159
    }
160
161
    /**
162
     * Deletes a file from the file system.
163
     *
164
     * @param string $filePath
165
     */
166
    public function delete($filePath)
167
    {
168
        if ($this->exists($filePath)) {
169
            $filePath = $this->calculateFilePath($filePath);
170
            unlink($filePath);
171
        }
172
    }
173
174
    /**
175
     * @param string $filePath
176
     *
177
     * @return bool
178
     */
179
    public function exists($filePath)
180
    {
181
        return file_exists($this->calculateFilePath($filePath));
182
    }
183
184
    /**
185
     * Deletes all file from the base directory given the current file system.
186
     */
187
    public function deleteAll()
188
    {
189
        $directory = $this->baseDir();
190
        $this->deleteAllRecursively($directory);
191
    }
192
193
    /**
194
     * @param string $directory
195
     */
196
    private function deleteAllRecursively($directory)
197
    {
198
        foreach (glob("{$directory}/*") as $file) {
199
            if (\is_dir($file)) {
200
                $this->deleteAllRecursively($file);
201
            } else {
202
                unlink($file);
203
            }
204
        }
205
206
        if ($this->baseDir() !== $directory) {
207
            rmdir($directory);
208
        }
209
    }
210
}
211