Completed
Push — master ( 89bfcf...4ab803 )
by Vladimir
02:41
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 Symfony\Component\Filesystem\Exception\FileNotFoundException;
12
use Symfony\Component\Filesystem\Exception\IOException;
13
use Symfony\Component\Finder\SplFileInfo;
14
15
/**
16
 * Class Filesystem.
17
 *
18
 * This class extends Symfony's Filesystem to provide convenience functions
19
 */
20
class Filesystem extends \Symfony\Component\Filesystem\Filesystem
21
{
22
    /**
23
     * Build an absolute file or directory path separated by the OS specific directory separator.
24
     *
25
     * @param string ...$pathFragments
26
     *
27
     * @return string
28
     */
29 185
    public function absolutePath($pathFragments)
30
    {
31 185
        if ($this->isAbsolutePath($pathFragments))
32
        {
33 183
            return $pathFragments;
34
        }
35
36 68
        $args = func_get_args();
37 68
        array_unshift($args, getcwd());
38
39 68
        return implode(DIRECTORY_SEPARATOR, $args);
40
    }
41
42
    /**
43
     * Build a file or directory path separated by the OS specific directory separator.
44
     *
45
     * @param string ...$pathFragments
46
     *
47
     * @return string
48
     */
49 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...
50
    {
51 58
        return implode(DIRECTORY_SEPARATOR, func_get_args());
52
    }
53
54
    /**
55
     * Copy a file or folder recursively.
56
     *
57
     * @param string $originFile          The original filename
58
     * @param string $targetFile          The target filename
59
     * @param bool   $overwriteNewerFiles If true, target files newer than origin files are overwritten
60
     *
61
     * @throws FileNotFoundException When originFile doesn't exist
62
     * @throws IOException           When copy fails
63
     */
64
    public function copy($originFile, $targetFile, $overwriteNewerFiles = false)
65
    {
66
        if ($this->isDir($originFile))
67
        {
68
            if (!$this->isDir($targetFile))
69
            {
70
                mkdir($targetFile, 0755, true);
71
            }
72
73
            $dir = dir($originFile);
74
75
            while (false !== $entry = $dir->read())
76
            {
77
                // Skip pointers
78
                if ($entry == '.' || $entry == '..')
79
                {
80
                    continue;
81
                }
82
83
                $this->copy("$originFile/$entry", "$targetFile/$entry", true);
84
            }
85
86
            $dir->close();
87
        }
88
        else
89
        {
90
            parent::copy($originFile, $targetFile, $overwriteNewerFiles);
91
        }
92
    }
93
94
    /**
95
     * Create an instance of Symfony's SplFileInfo with relative path information.
96
     *
97
     * @param string $filePath
98
     *
99
     * @return SplFileInfo
100
     */
101
    public function createSplFileInfo($filePath)
102
    {
103
        return new SplFileInfo(
104
            $this->absolutePath($filePath),
105
            $this->getRelativePath($this->getFolderPath($filePath)),
106
            $this->getRelativePath($filePath)
107
        );
108
    }
109
110
    /**
111
     * Strip the current working directory from an absolute path.
112
     *
113
     * @param string $path An absolute path
114
     *
115
     * @return string
116
     */
117 115
    public function getRelativePath($path)
118
    {
119 115
        return str_replace(getcwd() . DIRECTORY_SEPARATOR, '', $path);
120
    }
121
122
    /**
123
     * Get the name of a given file without the extension.
124
     *
125
     * @param string $filePath A file path
126
     *
127
     * @return string
128
     */
129 54
    public function getBaseName($filePath)
130
    {
131 54
        return pathinfo($filePath, PATHINFO_FILENAME);
132
    }
133
134
    /**
135
     * Get the name of a given file.
136
     *
137
     * @param string $filePath A file path
138
     *
139
     * @return string
140
     */
141 62
    public function getFileName($filePath)
142
    {
143 62
        return pathinfo($filePath, PATHINFO_BASENAME);
144
    }
145
146
    /**
147
     * Get the parent directory of a given file.
148
     *
149
     * @param string $filePath A file path
150
     *
151
     * @return string
152
     */
153 40
    public function getFolderPath($filePath)
154
    {
155 40
        return pathinfo($filePath, PATHINFO_DIRNAME);
156
    }
157
158
    /**
159
     * Get the extension of a given file.
160
     *
161
     * @param string $filename A file path
162
     *
163
     * @return string The extension of the file
164
     */
165 158
    public function getExtension($filename)
166
    {
167 158
        return pathinfo($filename, PATHINFO_EXTENSION);
168
    }
169
170
    /**
171
     * Check whether or not if a given path is a directory.
172
     *
173
     * @param string $folderPath
174
     *
175
     * @return bool
176
     */
177 36
    public function isDir($folderPath)
178
    {
179 36
        return is_dir($folderPath);
180
    }
181
182
    /**
183
     * Check whether a given file path is a symlink
184
     *
185
     * @param  string $filePath
186
     *
187
     * @return bool
188
     */
189 11
    public function isSymlink($filePath)
190
    {
191 11
        return is_link($filePath);
192
    }
193
194
    /**
195
     * Only read a file's contents if it's within the current working directory
196
     *
197
     * @param  string $filePath
198
     *
199
     * @return bool|string
200
     */
201 36
    public function safeReadFile($filePath)
202
    {
203 36
        $absPath = realpath($this->absolutePath($filePath));
204
205 36
        if (!$this->exists($absPath))
206
        {
207 1
            throw new FileNotFoundException(sprintf(
208 1
                "The '%s' file could not be found or is outside the website working directory",
209 1
                $filePath
210
            ));
211
        }
212
213 36
        if (strpos($absPath, getcwd()) !== 0)
214
        {
215
            throw new FileAccessDeniedException(sprintf(
216
                "The '%s' file is outside the website working directory",
217
                $filePath
218
            ));
219
        }
220
221 36
        return file_get_contents($absPath);
222
    }
223
224
    /**
225
     * Get the full path to the file without the extension.
226
     *
227
     * @param string $filename A file path
228
     *
229
     * @return string
230
     */
231 4
    public function removeExtension($filename)
232
    {
233 4
        return $this->appendPath(
234 4
            $this->getFolderPath($filename),
235 4
            $this->getBaseName($filename)
236
        );
237
    }
238
}
239