Complex classes like SafeFileHandlingTrait often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes. You can also have a look at the cohesion graph to spot any un-connected, or weakly-connected components.
Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.
While breaking up the class, it is a good idea to analyze how other classes use SafeFileHandlingTrait, and based on these observations, apply Extract Interface, too.
| 1 | <?php |
||
| 42 | trait SafeFileHandlingTrait |
||
| 43 | { |
||
| 44 | use FilePathNormalizerTrait; |
||
| 45 | /** |
||
| 46 | * Safely read contents of file. |
||
| 47 | * |
||
| 48 | * @param string $pathFile File name with absolute path. |
||
| 49 | * |
||
| 50 | * @return false|string Returns the file contents or false for any problems that prevent it. |
||
| 51 | */ |
||
| 52 | 41 | protected function safeFileRead(string $pathFile) |
|
| 67 | /** |
||
| 68 | * Safely write file using lock and temp file. |
||
| 69 | * |
||
| 70 | * @param string $pathFile File name with absolute path. |
||
| 71 | * |
||
| 72 | * @param string $data Contents to be written to file. |
||
| 73 | * |
||
| 74 | * @return bool Returns true if contents written, false on any problem that prevents write. |
||
| 75 | */ |
||
| 76 | 2 | protected function safeFileWrite(string $pathFile, string $data): bool |
|
| 101 | /** |
||
| 102 | * Used to acquire a exclusively locked file handle with a given mode and time limit. |
||
| 103 | * |
||
| 104 | * @param string $pathFile Name of file locked file handle is for. |
||
| 105 | * @param string $mode Mode to open handle with. Default will create |
||
| 106 | * the file if it does not exist. 'b' option should |
||
| 107 | * always be used to insure cross OS compatibility. |
||
| 108 | * @param int $timeout Time it seconds used while trying to get lock. |
||
| 109 | * Will be internally limited between 2 and 16 |
||
| 110 | * seconds. |
||
| 111 | * |
||
| 112 | * @return false|resource Returns exclusively locked file handle resource or false on errors. |
||
| 113 | */ |
||
| 114 | 42 | private function acquireLockedHandle(string $pathFile, string $mode = 'cb+', int $timeout = 2) |
|
| 126 | /** |
||
| 127 | * Used to acquire file handle lock that limits the time and number of tries to do so. |
||
| 128 | * |
||
| 129 | * @param resource $handle File handle to acquire exclusive lock for. |
||
| 130 | * @param int $timeout Maximum time in seconds to wait for lock. |
||
| 131 | * Internally limited between 2 and 16 seconds. |
||
| 132 | * Also determines how many tries to make. |
||
| 133 | * |
||
| 134 | * @return bool |
||
| 135 | */ |
||
| 136 | 42 | private function acquiredLock($handle, int $timeout): bool |
|
| 153 | /** |
||
| 154 | * Used to delete a file when unlink might fail and it needs to be retried. |
||
| 155 | * |
||
| 156 | * @param string $pathFile File name with absolute path. |
||
| 157 | * |
||
| 158 | * @return bool |
||
| 159 | */ |
||
| 160 | 8 | private function deleteWithRetry(string $pathFile): bool |
|
| 185 | /** |
||
| 186 | * Checks that path is readable, writable, and a directory. |
||
| 187 | * |
||
| 188 | * @param string $path Absolute path to be checked. |
||
| 189 | * |
||
| 190 | * @return bool Return true for writable directory else false. |
||
| 191 | */ |
||
| 192 | 2 | private function isWritablePath(string $path): bool |
|
| 197 | /** |
||
| 198 | * @param resource $handle |
||
| 199 | * |
||
| 200 | * @return void |
||
| 201 | */ |
||
| 202 | 42 | private function releaseHandle($handle) |
|
| 209 | /** |
||
| 210 | * Reads data from the named file while insuring it either receives full contents or fails. |
||
| 211 | * |
||
| 212 | * Things that can cause read to fail: |
||
| 213 | * |
||
| 214 | * * Unable to acquire exclusive file handle within calculated time or tries limits. |
||
| 215 | * * Read stalls without making any progress or repeatedly stalls to often. |
||
| 216 | * * Exceeds estimated read time based on file size with 2 second minimum enforced. |
||
| 217 | * |
||
| 218 | * @param string $pathFile Name of file to try reading from. |
||
| 219 | * |
||
| 220 | * @return false|string Returns contents of file or false for any errors that prevent it. |
||
| 221 | */ |
||
| 222 | 40 | private function safeDataRead(string $pathFile) |
|
| 253 | /** |
||
| 254 | * Write the data to file name using randomized tmp file, exclusive locking, and time limits. |
||
| 255 | * |
||
| 256 | * Things that can cause write to fail: |
||
| 257 | * |
||
| 258 | * * Unable to acquire exclusive file handle within calculated time or tries limits. |
||
| 259 | * * Write stalls without making any progress or repeatedly stalls to often. |
||
| 260 | * * Exceeds estimated write time based on file size with 2 second minimum enforced. |
||
| 261 | * |
||
| 262 | * @param string $pathFile File name with absolute path. |
||
| 263 | * |
||
| 264 | * @param string $data Contents to be written to file. |
||
| 265 | * |
||
| 266 | * @return bool Returns true if contents written, false on any problem that prevents write. |
||
| 267 | */ |
||
| 268 | 2 | private function safeDataWrite(string $pathFile, string $data): bool |
|
| 299 | } |
||
| 300 |