Completed
Push — master ( 4513c4...1bdcd4 )
by Vladimir
02:30
created

Filesystem::safeReadFile()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 22
Code Lines 11

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 8
CRAP Score 3.1825

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 22
rs 9.2
ccs 8
cts 11
cp 0.7272
cc 3
eloc 11
nc 3
nop 1
crap 3.1825
1
<?php
2
3
/**
4
 * @copyright 2017 Vladimir Jimenez
5
 * @license   https://github.com/allejo/stakx/blob/master/LICENSE.md MIT
6
 */
7
8
namespace allejo\stakx\System;
9
10
use allejo\stakx\Exception\FileAccessDeniedException;
11
use allejo\stakx\Filesystem\File;
12
use allejo\stakx\Filesystem\FilesystemPath;
13
use Symfony\Component\Filesystem\Exception\FileNotFoundException;
14
use Symfony\Component\Filesystem\Exception\IOException;
15
16
/**
17
 * Class Filesystem.
18
 *
19
 * This class extends Symfony's Filesystem to provide convenience functions
20
 */
21
class Filesystem extends \Symfony\Component\Filesystem\Filesystem
22
{
23
    /**
24
     * Build an absolute file or directory path separated by the OS specific directory separator.
25
     *
26
     * @param string ...$pathFragments
27
     *
28
     * @return string
29
     */
30 185
    public function absolutePath($pathFragments)
31
    {
32 185
        if ($this->isAbsolutePath($pathFragments))
33
        {
34 183
            return $pathFragments;
35
        }
36
37 68
        $args = func_get_args();
38 68
        array_unshift($args, getcwd());
39
40 68
        return implode(DIRECTORY_SEPARATOR, $args);
41
    }
42
43
    /**
44
     * Build a file or directory path separated by the OS specific directory separator.
45
     *
46
     * @param string ...$pathFragments
47
     *
48
     * @return string
49
     */
50 58
    public function appendPath($pathFragments)
0 ignored issues
show
Unused Code introduced by
The parameter $pathFragments is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
51
    {
52 58
        return implode(DIRECTORY_SEPARATOR, func_get_args());
53
    }
54
55
    /**
56
     * Copy a file or folder recursively.
57
     *
58
     * @param string $originFile          The original filename
59
     * @param string $targetFile          The target filename
60
     * @param bool   $overwriteNewerFiles If true, target files newer than origin files are overwritten
61
     *
62
     * @throws FileNotFoundException When originFile doesn't exist
63
     * @throws IOException           When copy fails
64
     */
65
    public function copy($originFile, $targetFile, $overwriteNewerFiles = false)
66
    {
67
        if ($this->isDir($originFile))
68
        {
69
            if (!$this->isDir($targetFile))
70
            {
71
                mkdir($targetFile, 0755, true);
72
            }
73
74
            $dir = dir($originFile);
75
76
            while (false !== $entry = $dir->read())
77
            {
78
                // Skip pointers
79
                if ($entry == '.' || $entry == '..')
80
                {
81
                    continue;
82
                }
83
84
                $this->copy("$originFile/$entry", "$targetFile/$entry", true);
85
            }
86
87
            $dir->close();
88
        }
89
        else
90
        {
91
            parent::copy($originFile, $targetFile, $overwriteNewerFiles);
92
        }
93
    }
94
95
    /**
96
     * Create an instance of stakx's File object with relative path information.
97
     *
98
     * @param string $filePath
99
     *
100
     * @return File
101
     */
102
    public function createFileObject($filePath)
103
    {
104
        return new File(
105
            $this->absolutePath($filePath),
106
            $this->getRelativePath($this->getFolderPath($filePath)),
107
            $this->getRelativePath($filePath)
108
        );
109
    }
110
111
    /**
112
     * Strip the current working directory from an absolute path.
113
     *
114
     * @param string $path An absolute path
115
     *
116
     * @return string
117
     */
118 115
    public function getRelativePath($path)
119
    {
120 115
        return str_replace(getcwd() . DIRECTORY_SEPARATOR, '', $path);
121
    }
122
123
    /**
124
     * Get the name of a given file without the extension.
125
     *
126
     * @param string $filePath A file path
127
     *
128
     * @return string
129
     */
130 55
    public function getBaseName($filePath)
131
    {
132 55
        return pathinfo($filePath, PATHINFO_FILENAME);
133
    }
134
135
    /**
136
     * Get the name of a given file.
137
     *
138
     * @param string $filePath A file path
139
     *
140
     * @return string
141
     */
142 63
    public function getFileName($filePath)
143
    {
144 63
        return pathinfo($filePath, PATHINFO_BASENAME);
145
    }
146
147
    /**
148
     * Get the parent directory of a given file.
149
     *
150
     * @param string $filePath A file path
151
     *
152
     * @return string
153
     */
154 135
    public function getFolderPath($filePath)
155
    {
156 135
        return pathinfo($filePath, PATHINFO_DIRNAME);
157
    }
158
159
    /**
160
     * Get the extension of a given file.
161
     *
162
     * @param string $filename A file path
163
     *
164
     * @return string The extension of the file
165
     */
166 158
    public function getExtension($filename)
167
    {
168 158
        return pathinfo($filename, PATHINFO_EXTENSION);
169
    }
170
171
    /**
172
     * Check whether or not if a given path is a directory.
173
     *
174
     * @param string $folderPath
175
     *
176
     * @return bool
177
     */
178 12
    public function isDir($folderPath)
179
    {
180 12
        return is_dir($folderPath);
181
    }
182
183
    /**
184
     * Check whether or not a given path is a file.
185
     *
186
     * @param string $filePath
187
     *
188
     * @return bool
189
     */
190
    public function isFile($filePath)
191
    {
192
        return is_file($filePath);
193
    }
194
195
    /**
196
     * Check whether a given file path is a symlink
197
     *
198
     * @param  string $filePath
199
     *
200
     * @return bool
201
     */
202 11
    public function isSymlink($filePath)
203
    {
204 11
        return is_link($filePath);
205
    }
206
207
    /**
208
     * Only read a file's contents if it's within the current working directory
209
     *
210
     * @param  string $filePath
211
     *
212
     * @return bool|string
213
     */
214 36
    public function safeReadFile($filePath)
215
    {
216 36
        $absPath = realpath($this->absolutePath($filePath));
217
218 36
        if (!$this->exists($absPath))
219
        {
220 1
            throw new FileNotFoundException(sprintf(
221 1
                "The '%s' file could not be found or is outside the website working directory",
222 1
                $filePath
223
            ));
224
        }
225
226 36
        if (strpos($absPath, getcwd()) !== 0)
227
        {
228
            throw new FileAccessDeniedException(sprintf(
229
                "The '%s' file is outside the website working directory",
230
                $filePath
231
            ));
232
        }
233
234 36
        return file_get_contents($absPath);
235
    }
236
237
    /**
238
     * Get the full path to the file without the extension.
239
     *
240
     * @param string $filename A file path
241
     *
242
     * @return string
243
     */
244 4
    public function removeExtension($filename)
245
    {
246 4
        return $this->appendPath(
247 4
            $this->getFolderPath($filename),
248 4
            $this->getBaseName($filename)
249
        );
250
    }
251
252
    public function path($path)
253
    {
254
        return (new FilesystemPath($path));
255
    }
256
}
257