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:
Complex classes like Connection 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 Connection, and based on these observations, apply Extract Interface, too.
| 1 | <?php |
||
| 8 | class Connection extends ClientConnection |
||
| 9 | { |
||
| 10 | const STATE_CONNECTING = 0; |
||
| 11 | const STATE_CONNECTED = 1; |
||
| 12 | const STATE_CREDS_SENT = 2; |
||
| 13 | const STATE_AUTHORIZED = 3; |
||
| 14 | |||
| 15 | const FLAG_PASSED = '\Passed'; |
||
| 16 | const FLAG_ANSWERED = '\Answered'; |
||
| 17 | const FLAG_SEEN = '\Seen'; |
||
| 18 | const FLAG_UNSEEN = '\Unseen'; |
||
| 19 | const FLAG_DELETED = '\Deleted'; |
||
| 20 | const FLAG_DRAFT = '\Draft'; |
||
| 21 | const FLAG_FLAGGED = '\Flagged'; |
||
| 22 | |||
| 23 | /** |
||
| 24 | * IMAP flags to search criteria |
||
| 25 | * @var array |
||
| 26 | */ |
||
| 27 | protected $searchFlags = [ |
||
| 28 | '\Recent' => 'RECENT', |
||
| 29 | '\Answered' => 'ANSWERED', |
||
| 30 | '\Seen' => 'SEEN', |
||
| 31 | '\Unseen' => 'UNSEEN', |
||
| 32 | '\Deleted' => 'DELETED', |
||
| 33 | '\Draft' => 'DRAFT', |
||
| 34 | '\Flagged' => 'FLAGGED', |
||
| 35 | ]; |
||
| 36 | |||
| 37 | const TAG_LOGIN = 'a01'; |
||
| 38 | const TAG_LIST = 'a02'; |
||
| 39 | const TAG_SELECT = 'a03'; |
||
| 40 | const TAG_FETCH = 'a04'; |
||
| 41 | const TAG_SEARCH = 'a05'; |
||
| 42 | const TAG_COUNT = 'a06'; |
||
| 43 | const TAG_SIZE = 'a07'; |
||
| 44 | const TAG_GETRAWMESSAGE = 'a08'; |
||
| 45 | const TAG_GETRAWHEADER = 'a09'; |
||
| 46 | const TAG_GETRAWCONTENT = 'a10'; |
||
| 47 | const TAG_GETUID = 'a11'; |
||
| 48 | const TAG_CREATEFOLDER = 'a12'; |
||
| 49 | const TAG_DELETEFOLDER = 'a13'; |
||
| 50 | const TAG_RENAMEFOLDER = 'a14'; |
||
| 51 | const TAG_STORE = 'a15'; |
||
| 52 | const TAG_DELETEMESSAGE = 'a16'; |
||
| 53 | const TAG_EXPUNGE = 'a17'; |
||
| 54 | const TAG_LOGOUT = 'a18'; |
||
| 55 | const TAG_STARTTLS = 'a19'; |
||
| 56 | |||
| 57 | protected $EOL = "\r\n"; |
||
| 58 | |||
| 59 | protected $state; |
||
| 60 | protected $lines = []; |
||
| 61 | protected $blob = ''; |
||
| 62 | protected $blobOctetsLeft = 0; |
||
| 63 | |||
| 64 | public function onReady() |
||
| 68 | |||
| 69 | /** |
||
| 70 | * escape a single literal |
||
| 71 | * @param $string |
||
| 72 | * @return string escaped list for imap |
||
| 73 | */ |
||
| 74 | protected function escapeString($string) |
||
| 78 | |||
| 79 | /** |
||
| 80 | * escape a list with literals or lists |
||
| 81 | * |
||
| 82 | * @param array $list list with literals or lists as PHP array |
||
| 83 | * @return string escaped list for imap |
||
| 84 | */ |
||
| 85 | protected function escapeList($list) |
||
| 97 | |||
| 98 | /** |
||
| 99 | * split a given line in tokens. a token is literal of any form or a list |
||
| 100 | * |
||
| 101 | * @param string $line line to decode |
||
| 102 | * @return array tokens, literals are returned as string, lists as array |
||
| 103 | */ |
||
| 104 | protected function decodeLine($line) |
||
| 168 | |||
| 169 | /** |
||
| 170 | * @param array $items |
||
| 171 | * @param string $from |
||
| 172 | * @param string $to |
||
| 173 | * @param bool $uid |
||
| 174 | * @param string $tag |
||
| 175 | */ |
||
| 176 | protected function fetch($items, $from, $to = null, $uid = false, $tag = self::TAG_FETCH) |
||
| 189 | |||
| 190 | /** |
||
| 191 | * @param array $flags |
||
| 192 | * @param string $from |
||
| 193 | * @param string $to |
||
| 194 | * @param string $mode (+/-) |
||
| 195 | * @param bool $silent |
||
| 196 | * @param string $tag |
||
| 197 | */ |
||
| 198 | protected function store(array $flags, $from, $to = null, $mode = null, $silent = true, $tag = self::TAG_STORE) |
||
| 214 | |||
| 215 | /** |
||
| 216 | * @param string $reference |
||
| 217 | * @param string $mailbox |
||
| 218 | */ |
||
| 219 | public function listFolders($cb, $reference = '', $mailbox = '*') |
||
| 225 | |||
| 226 | /** |
||
| 227 | * @param string $box |
||
| 228 | */ |
||
| 229 | public function selectBox($cb, $box = 'INBOX') |
||
| 234 | |||
| 235 | /** |
||
| 236 | * @param string $tag |
||
| 237 | */ |
||
| 238 | protected function expunge($tag = self::TAG_EXPUNGE) |
||
| 242 | |||
| 243 | /** |
||
| 244 | * @param string $haystack |
||
| 245 | * @param string $needle |
||
| 246 | */ |
||
| 247 | public function auth($cb, $login, $password) |
||
| 252 | |||
| 253 | /** |
||
| 254 | * @param array $params |
||
| 255 | * @param string $tag |
||
| 256 | */ |
||
| 257 | protected function searchMessages($params, $tag = self::TAG_SEARCH) |
||
| 261 | |||
| 262 | /** |
||
| 263 | * @param string $haystack |
||
| 264 | * @param string $needle |
||
| 265 | */ |
||
| 266 | protected function startsWith($haystack, $needle) |
||
| 271 | |||
| 272 | /** |
||
| 273 | * @param array $lines |
||
| 274 | */ |
||
| 275 | protected function decodeList($lines) |
||
| 297 | |||
| 298 | /** |
||
| 299 | * @param array $lines |
||
| 300 | */ |
||
| 301 | protected function decodeCount($lines) |
||
| 311 | |||
| 312 | /** |
||
| 313 | * @param array $lines |
||
| 314 | */ |
||
| 315 | protected function decodeGetUniqueId($lines) |
||
| 332 | |||
| 333 | /* |
||
| 334 | * @param array $lines |
||
| 335 | */ |
||
| 336 | protected function decodeSize($lines) |
||
| 356 | |||
| 357 | /** |
||
| 358 | * |
||
| 359 | * @param string $tag response tag |
||
| 360 | * @param string $type OK, NO, BAD |
||
| 361 | * @param string $line last response line |
||
| 362 | * @param array $lines full response |
||
| 363 | * @param string $blob |
||
| 364 | */ |
||
| 365 | protected function onCommand($tag, $type, $line, $lines, $blob) |
||
| 425 | |||
| 426 | public function onRead() |
||
| 470 | |||
| 471 | /** |
||
| 472 | * Count messages all messages in current box |
||
| 473 | * @param null $flags |
||
| 474 | */ |
||
| 475 | public function countMessages($cb, $flags = null) |
||
| 493 | |||
| 494 | /** |
||
| 495 | * get a list of messages with number and size |
||
| 496 | * @param int $uid number of message |
||
| 497 | */ |
||
| 498 | View Code Duplication | public function getSize($cb, $uid = null) |
|
| 507 | |||
| 508 | /** |
||
| 509 | * Fetch a message |
||
| 510 | * @param int $uid unique number of message |
||
| 511 | */ |
||
| 512 | public function getRawMessage($cb, $uid, $byUid = true) |
||
| 517 | |||
| 518 | /* |
||
| 519 | * Get raw header of message or part |
||
| 520 | * @param int $uid unique number of message |
||
| 521 | */ |
||
| 522 | public function getRawHeader($cb, $uid, $byUid = true) |
||
| 527 | |||
| 528 | /* |
||
| 529 | * Get raw content of message or part |
||
| 530 | * |
||
| 531 | * @param int $uid number of message |
||
| 532 | */ |
||
| 533 | public function getRawContent($cb, $uid, $byUid = true) |
||
| 538 | |||
| 539 | /** |
||
| 540 | * get unique id for one or all messages |
||
| 541 | * |
||
| 542 | * @param int|null $id message number |
||
| 543 | */ |
||
| 544 | View Code Duplication | public function getUniqueId($cb, $id = null) |
|
| 553 | |||
| 554 | /** |
||
| 555 | * create a new folder (and parent folders if needed) |
||
| 556 | * |
||
| 557 | * @param string $folder folder name |
||
| 558 | * @return bool success |
||
| 559 | */ |
||
| 560 | public function createFolder($cb, $folder, $parentFolder = null) |
||
| 568 | |||
| 569 | /** |
||
| 570 | * remove a folder |
||
| 571 | * |
||
| 572 | * @param string $name name or instance of folder |
||
| 573 | */ |
||
| 574 | public function removeFolder($cb, $folder) |
||
| 579 | |||
| 580 | /** |
||
| 581 | * rename and/or move folder |
||
| 582 | * @param string $oldName name or instance of folder |
||
| 583 | * @param string $newName new global name of folder |
||
| 584 | */ |
||
| 585 | public function renameFolder($cb, $oldName, $newName) |
||
| 591 | |||
| 592 | /** |
||
| 593 | * Remove a message from server. |
||
| 594 | * @param int $uid unique number of message |
||
| 595 | */ |
||
| 596 | public function removeMessage($cb, $uid) |
||
| 601 | |||
| 602 | /** |
||
| 603 | * logout of imap server |
||
| 604 | */ |
||
| 605 | public function logout($cb = null) |
||
| 612 | |||
| 613 | public function onFinish() |
||
| 618 | } |
||
| 619 |
This check marks implicit conversions of arrays to boolean values in a comparison. While in PHP an empty array is considered to be equal (but not identical) to false, this is not always apparent.
Consider making the comparison explicit by using
empty(..)or! empty(...)instead.