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 | * @param int $estimatedFileSize This is used to calculate the read buffer size to use as well as the |
||
| 50 | * proportional timeouts. |
||
| 51 | * |
||
| 52 | * @return false|string Returns the file contents or false for any problems that prevent it. |
||
| 53 | */ |
||
| 54 | protected function safeFileRead(string $pathFile, int $estimatedFileSize = 16777216) |
||
| 69 | /** |
||
| 70 | * Safely write file using lock and temp file. |
||
| 71 | * |
||
| 72 | * @param string $pathFile File name with absolute path. |
||
| 73 | * |
||
| 74 | * @param string $data Contents to be written to file. |
||
| 75 | * |
||
| 76 | * @return bool Returns true if contents written, false on any problem that prevents write. |
||
| 77 | */ |
||
| 78 | protected function safeFileWrite(string $pathFile, string $data): bool |
||
| 107 | /** |
||
| 108 | * Used to acquire a exclusively locked file handle with a given mode and time limit. |
||
| 109 | * |
||
| 110 | * @param string $pathFile Name of file locked file handle is for. |
||
| 111 | * @param string $mode Mode to open handle with. Default will create |
||
| 112 | * the file if it does not exist. 'b' option should |
||
| 113 | * always be used to insure cross OS compatibility. |
||
| 114 | * @param int $timeout Time it seconds used while trying to get lock. |
||
| 115 | * Will be internally limited between 2 and 16 |
||
| 116 | * seconds. |
||
| 117 | * |
||
| 118 | * @return false|resource Returns exclusively locked file handle resource or false on errors. |
||
| 119 | */ |
||
| 120 | private function acquireLockedHandle(string $pathFile, string $mode = 'cb+', int $timeout = 2) |
||
| 132 | /** |
||
| 133 | * Used to acquire file handle lock that limits the time and number of tries to do so. |
||
| 134 | * |
||
| 135 | * @param resource $handle File handle to acquire exclusive lock for. |
||
| 136 | * @param int $timeout Maximum time in seconds to wait for lock. |
||
| 137 | * Internally limited between 2 and 16 seconds. |
||
| 138 | * Also determines how many tries to make. |
||
| 139 | * |
||
| 140 | * @return bool |
||
| 141 | */ |
||
| 142 | private function acquiredLock($handle, int $timeout): bool |
||
| 160 | /** |
||
| 161 | * Used to delete a file when unlink might fail and it needs to be retried. |
||
| 162 | * |
||
| 163 | * @param string $pathFile File name with absolute path. |
||
| 164 | * |
||
| 165 | * @return bool |
||
| 166 | */ |
||
| 167 | private function deleteWithRetry(string $pathFile): bool |
||
| 192 | /** |
||
| 193 | * Checks that path is readable, writable, and a directory. |
||
| 194 | * |
||
| 195 | * @param string $path Absolute path to be checked. |
||
| 196 | * |
||
| 197 | * @return bool Return true for writable directory else false. |
||
| 198 | */ |
||
| 199 | private function isWritablePath(string $path): bool |
||
| 204 | /** |
||
| 205 | * @param resource $handle |
||
| 206 | * |
||
| 207 | * @return void |
||
| 208 | */ |
||
| 209 | private function releaseHandle($handle) |
||
| 216 | /** |
||
| 217 | * Reads data from the named file while insuring it either receives full contents or fails. |
||
| 218 | * |
||
| 219 | * Things that can cause read to fail: |
||
| 220 | * |
||
| 221 | * * Unable to acquire exclusive file handle within calculated time or tries limits. |
||
| 222 | * * Read stalls without making any progress or repeatedly stalls to often. |
||
| 223 | * * Exceeds estimated read time based on file size with 2 second minimum enforced. |
||
| 224 | * |
||
| 225 | * @param string $pathFile Name of file to try reading from. |
||
| 226 | * @param int $estimatedFileSize This is used to calculate the read |
||
| 227 | * buffer size to use as well as the |
||
| 228 | * proportional timeouts. |
||
| 229 | * |
||
| 230 | * @return false|string Returns contents of file or false for any errors that prevent it. |
||
| 231 | */ |
||
| 232 | private function safeDataRead(string $pathFile, int $estimatedFileSize) |
||
| 262 | /** |
||
| 263 | * Write the data to file name using randomized tmp file, exclusive locking, and time limits. |
||
| 264 | * |
||
| 265 | * Things that can cause write to fail: |
||
| 266 | * |
||
| 267 | * * Unable to acquire exclusive file handle within calculated time or tries limits. |
||
| 268 | * * Write stalls without making any progress or repeatedly stalls to often. |
||
| 269 | * * Exceeds estimated write time based on file size with 2 second minimum enforced. |
||
| 270 | * |
||
| 271 | * @param string $pathFile File name with absolute path. |
||
| 272 | * |
||
| 273 | * @param string $data Contents to be written to file. |
||
| 274 | * |
||
| 275 | * @return bool Returns true if contents written, false on any problem that prevents write. |
||
| 276 | */ |
||
| 277 | private function safeDataWrite(string $pathFile, string $data): bool |
||
| 308 | } |
||
| 309 |