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.