This project does not seem to handle request data directly as such no vulnerable execution paths were found.
include
, or for example
via PHP's auto-loading mechanism.
These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | <?php |
||
2 | /** |
||
3 | * This file is part of the NeedleProject\FileIo package. |
||
4 | * |
||
5 | * For the full copyright and license information, please view the LICENSE |
||
6 | * file that was distributed with this source code. |
||
7 | */ |
||
8 | namespace NeedleProject\FileIo; |
||
9 | |||
10 | use NeedleProject\FileIo\Content\ContentInterface; |
||
11 | use NeedleProject\FileIo\Exception\FileNotFoundException; |
||
12 | use NeedleProject\FileIo\Exception\IOException; |
||
13 | use NeedleProject\FileIo\Exception\PermissionDeniedException; |
||
14 | use NeedleProject\FileIo\Factory\ContentFactory; |
||
15 | use NeedleProject\FileIo\Helper\PathHelper; |
||
16 | use NeedleProject\Common\Util\ErrorToExceptionConverter; |
||
17 | |||
18 | /** |
||
19 | * Class File |
||
20 | * |
||
21 | * @package NeedleProject\FileIo |
||
22 | * @author Adrian Tilita <[email protected]> |
||
23 | * @copyright 2017 Adrian Tilita |
||
24 | * @license https://opensource.org/licenses/MIT MIT Licence |
||
25 | */ |
||
26 | class File |
||
27 | { |
||
28 | /** |
||
29 | * File extension separator |
||
30 | * @const string |
||
31 | */ |
||
32 | const EXTENSION_SEPARATOR = '.'; |
||
33 | |||
34 | /** |
||
35 | * File's name including the path |
||
36 | * @var null|string |
||
37 | */ |
||
38 | private $filenameWithPath = null; |
||
39 | |||
40 | /** |
||
41 | * File's extension - For no extension a blank string will be used |
||
42 | * @var null|string |
||
43 | */ |
||
44 | private $extension = null; |
||
45 | |||
46 | /** |
||
47 | * File's name without extension |
||
48 | * @var null|string |
||
49 | */ |
||
50 | private $name = null; |
||
51 | |||
52 | /** |
||
53 | * Whether the file has an extension or if it is set by us |
||
54 | * @var bool |
||
55 | */ |
||
56 | private $hasExtension = false; |
||
57 | |||
58 | /** |
||
59 | * @var null|ContentFactory |
||
60 | */ |
||
61 | private $contentFactory = null; |
||
62 | |||
63 | /** |
||
64 | * @var null|ErrorToExceptionConverter |
||
65 | */ |
||
66 | private $errorHandler = null; |
||
67 | |||
68 | /** |
||
69 | * File constructor. |
||
70 | * |
||
71 | * @param string $filenameWithPath |
||
72 | */ |
||
73 | 49 | public function __construct($filenameWithPath) |
|
74 | { |
||
75 | 49 | $pathHelper = new PathHelper(); |
|
76 | 49 | $this->filenameWithPath = $pathHelper->normalizePathSeparator($filenameWithPath); |
|
77 | 49 | $filename = $pathHelper->extractFilenameFromPath($this->filenameWithPath); |
|
78 | 49 | if (empty($filename) || false === $this->validatePath($this->filenameWithPath)) { |
|
79 | 2 | throw new \RuntimeException( |
|
80 | 2 | sprintf('Given path %s does not represents a file!', $filenameWithPath) |
|
81 | ); |
||
82 | } |
||
83 | 47 | list($this->name, $this->extension) = $pathHelper->splitFilename($filename); |
|
84 | 47 | $this->hasExtension = (bool)$this->extension; |
|
85 | 47 | $this->errorHandler = new ErrorToExceptionConverter(); |
|
86 | 47 | } |
|
87 | |||
88 | /** |
||
89 | * States whether the file actually exists on disk |
||
90 | * @return bool |
||
91 | */ |
||
92 | 48 | public function exists() |
|
0 ignored issues
–
show
|
|||
93 | { |
||
94 | 48 | return file_exists($this->filenameWithPath); |
|
95 | } |
||
96 | |||
97 | /** |
||
98 | * States whether the file is readable |
||
99 | * @return bool |
||
100 | */ |
||
101 | 9 | public function isReadable() |
|
102 | { |
||
103 | 9 | return is_readable($this->filenameWithPath); |
|
104 | } |
||
105 | |||
106 | /** |
||
107 | * @return bool |
||
108 | */ |
||
109 | 15 | public function isWritable() |
|
110 | { |
||
111 | 15 | if ($this->exists()) { |
|
112 | 15 | return is_writable($this->filenameWithPath); |
|
113 | } |
||
114 | $parts = explode(DIRECTORY_SEPARATOR, $this->filenameWithPath); |
||
115 | array_pop($parts); |
||
116 | return is_writable(implode(DIRECTORY_SEPARATOR, $parts)); |
||
117 | } |
||
118 | |||
119 | /** |
||
120 | * Write content to the current file |
||
121 | * |
||
122 | * @param \NeedleProject\FileIo\Content\ContentInterface $content |
||
123 | * @return \NeedleProject\FileIo\File |
||
124 | * @throws \NeedleProject\FileIo\Exception\PermissionDeniedException |
||
125 | */ |
||
126 | 11 | View Code Duplication | public function write(ContentInterface $content) |
0 ignored issues
–
show
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. ![]() |
|||
127 | { |
||
128 | 11 | if ($this->isWritable() === false) { |
|
129 | 1 | throw new PermissionDeniedException("The current file is not writable!"); |
|
130 | } |
||
131 | 10 | file_put_contents($this->filenameWithPath, $content->get()); |
|
132 | 10 | return $this; |
|
133 | } |
||
134 | |||
135 | /** |
||
136 | * @return \NeedleProject\FileIo\Content\ContentInterface |
||
0 ignored issues
–
show
|
|||
137 | * @throws \NeedleProject\FileIo\Exception\FileNotFoundException |
||
138 | * @throws \NeedleProject\FileIo\Exception\IOException |
||
139 | * @throws \NeedleProject\FileIo\Exception\PermissionDeniedException |
||
140 | */ |
||
141 | 9 | public function getContent() |
|
142 | { |
||
143 | 9 | if ($this->exists() === false) { |
|
144 | 2 | throw new FileNotFoundException(sprintf("%s does not exists!", $this->filenameWithPath)); |
|
145 | } |
||
146 | 7 | if ($this->isReadable() === false) { |
|
147 | 1 | throw new PermissionDeniedException( |
|
148 | 1 | sprintf("You do not have permissions to read file %s!", $this->filenameWithPath) |
|
149 | ); |
||
150 | } |
||
151 | 6 | $this->convertErrors(); |
|
152 | 6 | $stringContent = file_get_contents($this->filenameWithPath); |
|
153 | 5 | $this->resetErrorHandler(); |
|
154 | 5 | if (false === $stringContent) { |
|
155 | 1 | throw new IOException( |
|
156 | 1 | sprintf("Could not retrieve content! Error message: %s", error_get_last()['message']) |
|
157 | ); |
||
158 | } |
||
159 | 4 | return $this->getContentFactory() |
|
160 | 4 | ->create($this->extension, $stringContent); |
|
161 | } |
||
162 | |||
163 | /** |
||
164 | * Add content to the begging of the file |
||
165 | * @param string $content |
||
166 | * @return $this |
||
167 | * @throws \NeedleProject\FileIo\Exception\PermissionDeniedException |
||
168 | */ |
||
169 | 4 | View Code Duplication | public function appendContent($content) |
0 ignored issues
–
show
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. ![]() |
|||
170 | { |
||
171 | 4 | if ($this->isWritable() === false) { |
|
172 | 1 | throw new PermissionDeniedException("The current file is not writable!"); |
|
173 | } |
||
174 | 3 | file_put_contents($this->filenameWithPath, $content, FILE_APPEND); |
|
175 | 3 | return $this; |
|
176 | } |
||
177 | |||
178 | /** |
||
179 | * Add content to the begging of the file |
||
180 | * @param string $content |
||
181 | * @return $this |
||
182 | * @throws \NeedleProject\FileIo\Exception\PermissionDeniedException |
||
183 | */ |
||
184 | 4 | View Code Duplication | public function prependContent($content) |
0 ignored issues
–
show
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. ![]() |
|||
185 | { |
||
186 | 4 | if ($this->isWritable() === false) { |
|
187 | 1 | throw new PermissionDeniedException("The current file is not writable!"); |
|
188 | } |
||
189 | 3 | file_put_contents($this->filenameWithPath, $content . $this->getContent()->get()); |
|
190 | 3 | return $this; |
|
191 | } |
||
192 | |||
193 | /** |
||
194 | * Deletes the current file |
||
195 | * @return bool |
||
196 | * @throws \NeedleProject\FileIo\Exception\IOException |
||
197 | */ |
||
198 | 3 | public function delete() |
|
0 ignored issues
–
show
function delete() does not seem to conform to the naming convention (^(?:is|has|should|may|supports) ).
This check examines a number of code elements and verifies that they conform to the given naming conventions. You can set conventions for local variables, abstract classes, utility classes, constant, properties, methods, parameters, interfaces, classes, exceptions and special methods. ![]() |
|||
199 | { |
||
200 | 3 | if ($this->exists() === false) { |
|
201 | 2 | return false; |
|
202 | } |
||
203 | 1 | $this->convertErrors(); |
|
204 | 1 | $unlinkResult = unlink($this->filenameWithPath); |
|
205 | 1 | $this->resetErrorHandler(); |
|
206 | 1 | return $unlinkResult; |
|
207 | } |
||
208 | |||
209 | /** |
||
210 | * State existence of a file's extension |
||
211 | * @return bool |
||
212 | */ |
||
213 | 10 | public function hasExtension() |
|
214 | { |
||
215 | 10 | return $this->hasExtension; |
|
216 | } |
||
217 | |||
218 | /** |
||
219 | * Get file's extension |
||
220 | * @return string |
||
0 ignored issues
–
show
|
|||
221 | */ |
||
222 | 4 | public function getExtension() |
|
223 | { |
||
224 | 4 | return $this->extension; |
|
225 | } |
||
226 | |||
227 | /** |
||
228 | * Get file's name without extension |
||
229 | * @return string |
||
0 ignored issues
–
show
|
|||
230 | */ |
||
231 | 4 | public function getName() |
|
232 | { |
||
233 | 4 | return $this->name; |
|
234 | } |
||
235 | |||
236 | /** |
||
237 | * Get file's name with extension |
||
238 | * @return string |
||
0 ignored issues
–
show
|
|||
239 | */ |
||
240 | 5 | public function getBasename() |
|
241 | { |
||
242 | 5 | if (false === $this->hasExtension()) { |
|
243 | 1 | return $this->name; |
|
244 | } |
||
245 | 4 | return $this->name . static::EXTENSION_SEPARATOR . $this->extension; |
|
246 | } |
||
247 | |||
248 | /** |
||
249 | * Returns a factory responsible for creating appropriate content |
||
250 | * @return \NeedleProject\FileIo\Factory\ContentFactory |
||
251 | */ |
||
252 | 4 | protected function getContentFactory() |
|
253 | { |
||
254 | 4 | if (is_null($this->contentFactory)) { |
|
255 | 4 | $this->contentFactory = new ContentFactory(); |
|
256 | } |
||
257 | 4 | return $this->contentFactory; |
|
258 | } |
||
259 | |||
260 | /** |
||
261 | * Validate if the given path is not a directory |
||
262 | * @param string $filenameWithPath |
||
263 | * @return bool |
||
264 | */ |
||
265 | 48 | private function validatePath($filenameWithPath) |
|
0 ignored issues
–
show
function validatePath() does not seem to conform to the naming convention (^(?:is|has|should|may|supports) ).
This check examines a number of code elements and verifies that they conform to the given naming conventions. You can set conventions for local variables, abstract classes, utility classes, constant, properties, methods, parameters, interfaces, classes, exceptions and special methods. ![]() |
|||
266 | { |
||
267 | 48 | return !($this->exists() && is_dir($filenameWithPath)); |
|
268 | } |
||
269 | |||
270 | /** |
||
271 | * Convert errors to Exception type objects |
||
272 | */ |
||
273 | 7 | protected function convertErrors() |
|
274 | { |
||
275 | 7 | $this->errorHandler->convertErrorsToExceptions(E_ALL, IOException::class); |
|
276 | 7 | } |
|
277 | |||
278 | /** |
||
279 | * Undo error to exception conversion |
||
280 | */ |
||
281 | 6 | protected function resetErrorHandler() |
|
282 | { |
||
283 | 6 | $this->errorHandler->restoreErrorHandler(); |
|
284 | 6 | } |
|
285 | } |
||
286 |
This check examines a number of code elements and verifies that they conform to the given naming conventions.
You can set conventions for local variables, abstract classes, utility classes, constant, properties, methods, parameters, interfaces, classes, exceptions and special methods.