Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.
Common duplication problems, and corresponding solutions are:
1 | <?php |
||
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) |
|
87 | |||
88 | /** |
||
89 | * States whether the file actually exists on disk |
||
90 | * @return bool |
||
91 | */ |
||
92 | 48 | public function exists() |
|
96 | |||
97 | /** |
||
98 | * States whether the file is readable |
||
99 | * @return bool |
||
100 | */ |
||
101 | 9 | public function isReadable() |
|
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) |
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 |
||
137 | * @throws \NeedleProject\FileIo\Exception\FileNotFoundException |
||
138 | * @throws \NeedleProject\FileIo\Exception\IOException |
||
139 | * @throws \NeedleProject\FileIo\Exception\PermissionDeniedException |
||
140 | */ |
||
141 | 9 | public function getContent() |
|
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) |
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) |
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() |
|
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() |
|
217 | |||
218 | /** |
||
219 | * Get file's extension |
||
220 | * @return string |
||
221 | */ |
||
222 | 4 | public function getExtension() |
|
226 | |||
227 | /** |
||
228 | * Get file's name without extension |
||
229 | * @return string |
||
230 | */ |
||
231 | 4 | public function getName() |
|
235 | |||
236 | /** |
||
237 | * Get file's name with extension |
||
238 | * @return string |
||
239 | */ |
||
240 | 5 | public function getBasename() |
|
247 | |||
248 | /** |
||
249 | * Returns a factory responsible for creating appropriate content |
||
250 | * @return \NeedleProject\FileIo\Factory\ContentFactory |
||
251 | */ |
||
252 | 4 | protected function getContentFactory() |
|
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) |
|
269 | |||
270 | /** |
||
271 | * Convert errors to Exception type objects |
||
272 | */ |
||
273 | 7 | protected function convertErrors() |
|
277 | |||
278 | /** |
||
279 | * Undo error to exception conversion |
||
280 | */ |
||
281 | 6 | protected function resetErrorHandler() |
|
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.