Complex classes like Stream 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 Stream, and based on these observations, apply Extract Interface, too.
| 1 | <?php |
||
| 31 | class Stream implements SeekableIterator |
||
| 32 | { |
||
| 33 | use ValidatorTrait; |
||
| 34 | |||
| 35 | /** |
||
| 36 | * Attached filters |
||
| 37 | * |
||
| 38 | * @var resource[] |
||
| 39 | */ |
||
| 40 | protected $filters = []; |
||
| 41 | |||
| 42 | /** |
||
| 43 | * stream resource |
||
| 44 | * |
||
| 45 | * @var resource |
||
| 46 | */ |
||
| 47 | protected $stream; |
||
| 48 | |||
| 49 | /** |
||
| 50 | * Tell whether the stream should be closed on object destruction |
||
| 51 | * |
||
| 52 | * @var bool |
||
| 53 | */ |
||
| 54 | protected $should_close_stream = false; |
||
| 55 | |||
| 56 | /** |
||
| 57 | * Current iterator value |
||
| 58 | * |
||
| 59 | * @var mixed |
||
| 60 | */ |
||
| 61 | protected $value; |
||
| 62 | |||
| 63 | /** |
||
| 64 | * Current iterator key |
||
| 65 | * |
||
| 66 | * @var int |
||
| 67 | */ |
||
| 68 | protected $offset; |
||
| 69 | |||
| 70 | /** |
||
| 71 | * Flags for the Document |
||
| 72 | * |
||
| 73 | * @var int |
||
| 74 | */ |
||
| 75 | protected $flags = 0; |
||
| 76 | |||
| 77 | /** |
||
| 78 | * the field delimiter (one character only) |
||
| 79 | * |
||
| 80 | * @var string |
||
| 81 | */ |
||
| 82 | protected $delimiter = ','; |
||
| 83 | |||
| 84 | /** |
||
| 85 | * the field enclosure character (one character only) |
||
| 86 | * |
||
| 87 | * @var string |
||
| 88 | */ |
||
| 89 | protected $enclosure = '"'; |
||
| 90 | |||
| 91 | /** |
||
| 92 | * the field escape character (one character only) |
||
| 93 | * |
||
| 94 | * @var string |
||
| 95 | */ |
||
| 96 | protected $escape = '\\'; |
||
| 97 | |||
| 98 | /** |
||
| 99 | * New instance |
||
| 100 | * |
||
| 101 | * @param resource $resource stream type resource |
||
| 102 | * |
||
| 103 | * @throws RuntimeException if the argument passed is not a seeakable stream resource |
||
| 104 | */ |
||
| 105 | 34 | public function __construct($resource) |
|
| 121 | |||
| 122 | /** |
||
| 123 | * Create a resource. |
||
| 124 | * |
||
| 125 | * @param string $url file url |
||
| 126 | * @param string $open_mode the file open mode flag |
||
| 127 | * @param null $context the resource context |
||
| 128 | * |
||
| 129 | * @throws Exception if the stream resource can not be created |
||
| 130 | * |
||
| 131 | * @return resource |
||
| 132 | */ |
||
| 133 | 10 | private static function createResource(string $url, string $open_mode, $context) |
|
| 147 | |||
| 148 | /** |
||
| 149 | * @inheritdoc |
||
| 150 | */ |
||
| 151 | public function __destruct() |
||
| 165 | |||
| 166 | /** |
||
| 167 | * @inheritdoc |
||
| 168 | */ |
||
| 169 | 2 | public function __clone() |
|
| 173 | |||
| 174 | /** |
||
| 175 | * @inheritdoc |
||
| 176 | */ |
||
| 177 | 2 | public function __debugInfo() |
|
| 186 | |||
| 187 | /** |
||
| 188 | * Return a new instance from a file path |
||
| 189 | * |
||
| 190 | * @param string $path file path |
||
| 191 | * @param string $open_mode the file open mode flag |
||
| 192 | * @param resource|null $context the resource context |
||
| 193 | * |
||
| 194 | * @throws Exception if the stream resource can not be created |
||
| 195 | * |
||
| 196 | * @return static |
||
| 197 | */ |
||
| 198 | 12 | public static function createFromPath(string $path, string $open_mode = 'r', $context = null): self |
|
| 207 | |||
| 208 | /** |
||
| 209 | * Return a new instance from a file url. |
||
| 210 | * |
||
| 211 | * @param string $url file url |
||
| 212 | * @param string $open_mode the file open mode flag |
||
| 213 | * @param null $context the resource context |
||
| 214 | * |
||
| 215 | * @see http://php.net/manual/es/wrappers.php |
||
| 216 | * |
||
| 217 | * @throws Exception if the stream resource can not be created |
||
| 218 | * |
||
| 219 | * @return static |
||
| 220 | */ |
||
| 221 | public static function createFromUrl(string $url, string $open_mode = 'r', $context = null): self |
||
| 235 | |||
| 236 | /** |
||
| 237 | * Return a new instance from a string |
||
| 238 | * |
||
| 239 | * @param string $content the CSV document as a string |
||
| 240 | * |
||
| 241 | * @return static |
||
| 242 | */ |
||
| 243 | 10 | public static function createFromString(string $content): self |
|
| 253 | |||
| 254 | /** |
||
| 255 | * append a filter |
||
| 256 | * |
||
| 257 | * @see http://php.net/manual/en/function.stream-filter-append.php |
||
| 258 | * |
||
| 259 | * @param string $filtername |
||
| 260 | * @param int $read_write |
||
| 261 | * @param mixed $params |
||
| 262 | * |
||
| 263 | * @throws Exception if the filter can not be appended |
||
| 264 | */ |
||
| 265 | 10 | public function appendFilter(string $filtername, int $read_write, $params = null) |
|
| 276 | |||
| 277 | /** |
||
| 278 | * Set CSV control |
||
| 279 | * |
||
| 280 | * @see http://php.net/manual/en/splfileobject.setcsvcontrol.php |
||
| 281 | * |
||
| 282 | * @param string $delimiter |
||
| 283 | * @param string $enclosure |
||
| 284 | * @param string $escape |
||
| 285 | */ |
||
| 286 | 22 | public function setCsvControl(string $delimiter = ',', string $enclosure = '"', string $escape = '\\') |
|
| 292 | |||
| 293 | /** |
||
| 294 | * Set CSV control |
||
| 295 | * |
||
| 296 | * @see http://php.net/manual/en/splfileobject.getcsvcontrol.php |
||
| 297 | * |
||
| 298 | * @return string[] |
||
| 299 | */ |
||
| 300 | 28 | public function getCsvControl() |
|
| 304 | |||
| 305 | /** |
||
| 306 | * Set CSV stream flags |
||
| 307 | * |
||
| 308 | * @see http://php.net/manual/en/splfileobject.setflags.php |
||
| 309 | * |
||
| 310 | * @param int $flags |
||
| 311 | */ |
||
| 312 | 22 | public function setFlags(int $flags) |
|
| 316 | |||
| 317 | /** |
||
| 318 | * Write a field array as a CSV line |
||
| 319 | * |
||
| 320 | * @see http://php.net/manual/en/splfileobject.fputcsv.php |
||
| 321 | * |
||
| 322 | * @param array $fields |
||
| 323 | * @param string $delimiter |
||
| 324 | * @param string $enclosure |
||
| 325 | * @param string $escape |
||
| 326 | * |
||
| 327 | * @return int|bool |
||
| 328 | */ |
||
| 329 | 14 | public function fputcsv(array $fields, string $delimiter = ',', string $enclosure = '"', string $escape = '\\') |
|
| 339 | |||
| 340 | /** |
||
| 341 | * Get line number |
||
| 342 | * |
||
| 343 | * @see http://php.net/manual/en/splfileobject.key.php |
||
| 344 | * |
||
| 345 | * @return int |
||
| 346 | */ |
||
| 347 | 12 | public function key() |
|
| 351 | |||
| 352 | /** |
||
| 353 | * Read next line |
||
| 354 | * |
||
| 355 | * @see http://php.net/manual/en/splfileobject.next.php |
||
| 356 | * |
||
| 357 | */ |
||
| 358 | 12 | public function next() |
|
| 363 | |||
| 364 | /** |
||
| 365 | * Rewind the file to the first line |
||
| 366 | * |
||
| 367 | * @see http://php.net/manual/en/splfileobject.rewind.php |
||
| 368 | * |
||
| 369 | */ |
||
| 370 | 22 | public function rewind() |
|
| 379 | |||
| 380 | /** |
||
| 381 | * Not at EOF |
||
| 382 | * |
||
| 383 | * @see http://php.net/manual/en/splfileobject.valid.php |
||
| 384 | * |
||
| 385 | * @return bool |
||
| 386 | */ |
||
| 387 | 20 | public function valid() |
|
| 395 | |||
| 396 | /** |
||
| 397 | * Retrieves the current line of the file. |
||
| 398 | * |
||
| 399 | * @see http://php.net/manual/en/splfileobject.current.php |
||
| 400 | * |
||
| 401 | * @return mixed |
||
| 402 | */ |
||
| 403 | 26 | public function current() |
|
| 413 | |||
| 414 | /** |
||
| 415 | * Retrieves the current line as a CSV Record |
||
| 416 | * |
||
| 417 | * @return array|bool |
||
| 418 | */ |
||
| 419 | 22 | protected function getCurrentRecord() |
|
| 427 | |||
| 428 | /** |
||
| 429 | * Seek to specified line |
||
| 430 | * |
||
| 431 | * @see http://php.net/manual/en/splfileobject.seek.php |
||
| 432 | * |
||
| 433 | * |
||
| 434 | * @param int $position |
||
| 435 | * @throws Exception if the position is negative |
||
| 436 | */ |
||
| 437 | 8 | public function seek($position) |
|
| 452 | |||
| 453 | /** |
||
| 454 | * Output all remaining data on a file pointer |
||
| 455 | * |
||
| 456 | * @see http://php.net/manual/en/splfileobject.fpatssthru.php |
||
| 457 | * |
||
| 458 | * @return int |
||
| 459 | */ |
||
| 460 | 2 | public function fpassthru() |
|
| 464 | |||
| 465 | /** |
||
| 466 | * Read from file |
||
| 467 | * |
||
| 468 | * @see http://php.net/manual/en/splfileobject.fread.php |
||
| 469 | * |
||
| 470 | * @param int $length The number of bytes to read |
||
| 471 | * |
||
| 472 | * @return string|false |
||
| 473 | */ |
||
| 474 | 8 | public function fread($length) |
|
| 478 | |||
| 479 | /** |
||
| 480 | * Seek to a position |
||
| 481 | * |
||
| 482 | * @see http://php.net/manual/en/splfileobject.fseek.php |
||
| 483 | * |
||
| 484 | * @param int $offset |
||
| 485 | * @param int $whence |
||
| 486 | * |
||
| 487 | * @return int |
||
| 488 | */ |
||
| 489 | 10 | public function fseek(int $offset, int $whence = SEEK_SET) |
|
| 493 | |||
| 494 | /** |
||
| 495 | * Write to stream |
||
| 496 | * |
||
| 497 | * @see http://php.net/manual/en/splfileobject.fwrite.php |
||
| 498 | * |
||
| 499 | * @param string $str |
||
| 500 | * @param int $length |
||
| 501 | * |
||
| 502 | * @return int|bool |
||
| 503 | */ |
||
| 504 | 2 | public function fwrite(string $str, int $length = 0) |
|
| 508 | |||
| 509 | /** |
||
| 510 | * Flushes the output to a file |
||
| 511 | * |
||
| 512 | * @see http://php.net/manual/en/splfileobject.fwrite.php |
||
| 513 | * |
||
| 514 | * @return bool |
||
| 515 | */ |
||
| 516 | 2 | public function fflush() |
|
| 520 | } |
||
| 521 |
This check looks at variables that have been passed in as parameters and are passed out again to other methods.
If the outgoing method call has stricter type requirements than the method itself, an issue is raised.
An additional type check may prevent trouble.