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 Part 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 Part, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
11 | class Part implements \RecursiveIterator |
||
12 | { |
||
13 | const TYPE_TEXT = 'text'; |
||
14 | const TYPE_MULTIPART = 'multipart'; |
||
15 | const TYPE_MESSAGE = 'message'; |
||
16 | const TYPE_APPLICATION = 'application'; |
||
17 | const TYPE_AUDIO = 'audio'; |
||
18 | const TYPE_IMAGE = 'image'; |
||
19 | const TYPE_VIDEO = 'video'; |
||
20 | const TYPE_OTHER = 'other'; |
||
21 | const TYPE_UNKNOWN = 'unknown'; |
||
22 | |||
23 | const ENCODING_7BIT = '7bit'; |
||
24 | const ENCODING_8BIT = '8bit'; |
||
25 | const ENCODING_BINARY = 'binary'; |
||
26 | const ENCODING_BASE64 = 'base64'; |
||
27 | const ENCODING_QUOTED_PRINTABLE = 'quoted-printable'; |
||
28 | const ENCODING_UNKNOWN = 'unknown'; |
||
29 | |||
30 | const SUBTYPE_TEXT = 'TEXT'; |
||
31 | const SUBTYPE_HTML = 'HTML'; |
||
32 | |||
33 | protected $typesMap = array( |
||
34 | 0 => self::TYPE_TEXT, |
||
35 | 1 => self::TYPE_MULTIPART, |
||
36 | 2 => self::TYPE_MESSAGE, |
||
37 | 3 => self::TYPE_APPLICATION, |
||
38 | 4 => self::TYPE_AUDIO, |
||
39 | 5 => self::TYPE_IMAGE, |
||
40 | 6 => self::TYPE_VIDEO, |
||
41 | 7 => self::TYPE_OTHER |
||
42 | ); |
||
43 | |||
44 | protected $encodingsMap = array( |
||
45 | 0 => self::ENCODING_7BIT, |
||
46 | 1 => self::ENCODING_8BIT, |
||
47 | 2 => self::ENCODING_BINARY, |
||
48 | 3 => self::ENCODING_BASE64, |
||
49 | 4 => self::ENCODING_QUOTED_PRINTABLE, |
||
50 | 5 => self::ENCODING_UNKNOWN |
||
51 | ); |
||
52 | |||
53 | protected $type; |
||
54 | |||
55 | protected $subtype; |
||
56 | |||
57 | protected $encoding; |
||
58 | |||
59 | protected $bytes; |
||
60 | |||
61 | protected $lines; |
||
62 | |||
63 | /** |
||
64 | * @var Parameters |
||
65 | */ |
||
66 | protected $parameters; |
||
67 | |||
68 | protected $stream; |
||
69 | |||
70 | protected $messageNumber; |
||
71 | |||
72 | protected $partNumber; |
||
73 | |||
74 | protected $structure; |
||
75 | |||
76 | protected $content; |
||
77 | |||
78 | protected $decodedContent; |
||
79 | |||
80 | protected $parts = array(); |
||
81 | |||
82 | protected $key = 0; |
||
83 | |||
84 | protected $disposition; |
||
85 | |||
86 | /** |
||
87 | * Constructor |
||
88 | * |
||
89 | * @param resource $stream IMAP stream |
||
90 | * @param int $messageNumber Message number |
||
91 | * @param int $partNumber Part number (optional) |
||
92 | * @param \stdClass $structure Part structure |
||
93 | */ |
||
94 | public function __construct( |
||
106 | |||
107 | public function getCharset() |
||
111 | |||
112 | public function getType() |
||
116 | |||
117 | public function getSubtype() |
||
121 | |||
122 | public function getEncoding() |
||
126 | |||
127 | public function getBytes() |
||
131 | |||
132 | public function getLines() |
||
136 | |||
137 | public function getParameters() |
||
141 | |||
142 | /** |
||
143 | * Get raw part content |
||
144 | * |
||
145 | * @return string |
||
146 | */ |
||
147 | public function getContent($keepUnseen = false) |
||
155 | |||
156 | /** |
||
157 | * Get decoded part content |
||
158 | * |
||
159 | * @return string |
||
160 | */ |
||
161 | public function getDecodedContent($keepUnseen = false) |
||
194 | |||
195 | public function getStructure() |
||
199 | |||
200 | protected function fetchStructure($partNumber = null) |
||
212 | |||
213 | protected function parseStructure(\stdClass $structure) { |
||
262 | |||
263 | /** |
||
264 | * Get an array of all parts for this message |
||
265 | * |
||
266 | * @return self[] |
||
267 | */ |
||
268 | public function getParts() |
||
272 | |||
273 | public function current() |
||
277 | |||
278 | public function getChildren() |
||
282 | |||
283 | public function hasChildren() |
||
287 | |||
288 | public function key() |
||
292 | |||
293 | public function next() |
||
297 | |||
298 | public function rewind() |
||
302 | |||
303 | public function valid() |
||
307 | |||
308 | public function getDisposition() |
||
312 | |||
313 | /** |
||
314 | * Get raw message content |
||
315 | * |
||
316 | * @param bool $keepUnseen Whether to keep the message unseen. |
||
317 | * Default behaviour is set set the seen flag when |
||
318 | * getting content. |
||
319 | * |
||
320 | * @return string |
||
321 | */ |
||
322 | protected function doGetContent($keepUnseen = false) |
||
331 | |||
332 | private function isAttachment($part) { |
||
366 | } |
||
367 |
It seems like you allow that null is being passed for a parameter, however the function which is called does not seem to accept null.
We recommend to add an additional type check (or disallow null for the parameter):