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 Swift_Message 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 Swift_Message, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
26 | class Swift_Message extends Swift_Message_Mime |
||
27 | { |
||
28 | /** |
||
29 | * Constant from a high priority message (pretty meaningless) |
||
30 | */ |
||
31 | const PRIORITY_HIGH = 1; |
||
32 | /** |
||
33 | * Constant for a low priority message |
||
34 | */ |
||
35 | const PRIORITY_LOW = 5; |
||
36 | /** |
||
37 | * Constant for a normal priority message |
||
38 | */ |
||
39 | const PRIORITY_NORMAL = 3; |
||
40 | /** |
||
41 | * The MIME warning for client not supporting multipart content |
||
42 | * @var string |
||
43 | */ |
||
44 | protected $mimeWarning = null; |
||
45 | /** |
||
46 | * The version of the library (Swift) if known. |
||
47 | * @var string |
||
48 | */ |
||
49 | protected $libVersion = ""; |
||
50 | /** |
||
51 | * A container for references to other objects. |
||
52 | * This is used in some very complex logic when sub-parts get shifted around. |
||
53 | * @var array |
||
54 | */ |
||
55 | protected $references = array( |
||
56 | "parent" => array("alternative" => null, "mixed" => null, "related" => null), |
||
57 | "alternative" => array(), |
||
58 | "mixed" => array(), |
||
59 | "related" => array() |
||
60 | ); |
||
61 | |||
62 | /** |
||
63 | * Ctor. |
||
64 | * @param string Message subject |
||
65 | * @param string Body |
||
66 | * @param string Content-type |
||
67 | * @param string Encoding |
||
68 | * @param string Charset |
||
69 | * @param string $encoding |
||
|
|||
70 | * @param string $charset |
||
71 | */ |
||
72 | public function __construct($subject="", $body=null, $type="text/plain", $encoding=null, $charset=null) |
||
119 | /** |
||
120 | * Sets a reference so when nodes are nested, operations can be redirected. |
||
121 | * This really should be refactored to use just one array rather than dynamic variables. |
||
122 | * @param string Key 1 |
||
123 | * @param string Key 2 |
||
124 | * @param Object Reference |
||
125 | * @param string $where |
||
126 | */ |
||
127 | protected function setReference($where, $key, $ref) |
||
132 | /** |
||
133 | * Get a reference to an object (for complex reasons). |
||
134 | * @param string Key 1 |
||
135 | * @param string Key 2 |
||
136 | * @param string $where |
||
137 | * @return Object |
||
138 | */ |
||
139 | protected function getReference($where, $key) |
||
144 | /** |
||
145 | * Get the level in the MIME hierarchy at which this section should appear. |
||
146 | * @return string |
||
147 | */ |
||
148 | public function getLevel() |
||
152 | /** |
||
153 | * Set the message id literally. |
||
154 | * Unless you know what you are doing you should be using generateId() rather than this method, |
||
155 | * otherwise you may break compliancy with RFC 2822. |
||
156 | * @param string The message ID string. |
||
157 | * @param null|string $id |
||
158 | */ |
||
159 | public function setId($id) |
||
163 | /** |
||
164 | * Create a RFC 2822 compliant message id, optionally based upon $idstring. |
||
165 | * The message ID includes information about the current time, the server and some random characters. |
||
166 | * @param string An optional string the base the ID on |
||
167 | * @return string The generated message ID, including the <> quotes. |
||
168 | * @author Cristian Rodriguez <[email protected]> |
||
169 | */ |
||
170 | public function generateId($idstring=null) |
||
182 | /** |
||
183 | * Get the generated message ID for this message, including the <> quotes. |
||
184 | * If generated automatically, or using generateId() this method returns a RFC2822 compliant Message-ID. |
||
185 | * @return string |
||
186 | * @author Cristian Rodriguez <[email protected]> |
||
187 | */ |
||
188 | public function getId() |
||
192 | /** |
||
193 | * Set the address in the Return-Path: header |
||
194 | * @param string The bounce-detect address |
||
195 | */ |
||
196 | public function setReturnPath($address) |
||
201 | /** |
||
202 | * Return the address used in the Return-Path: header |
||
203 | * @return string |
||
204 | * @param boolean Return the address for SMTP command |
||
205 | */ |
||
206 | public function getReturnPath($smtp=false) |
||
219 | /** |
||
220 | * Set the address in the From: header |
||
221 | * @param string The address to set as From |
||
222 | */ |
||
223 | public function setFrom($from) |
||
228 | /** |
||
229 | * Get the address used in the From: header |
||
230 | * @return string |
||
231 | */ |
||
232 | public function getFrom() |
||
236 | /** |
||
237 | * Set the list of recipients in the To: header |
||
238 | * @param mixed An array or a string |
||
239 | */ |
||
240 | View Code Duplication | public function setTo($to) |
|
252 | /** |
||
253 | * Return the list of recipients in the To: header |
||
254 | * @return array |
||
255 | */ |
||
256 | public function getTo() |
||
265 | /** |
||
266 | * Set the list of recipients in the Reply-To: header |
||
267 | * @param mixed An array or a string |
||
268 | */ |
||
269 | View Code Duplication | public function setReplyTo($replyto) |
|
281 | /** |
||
282 | * Return the list of recipients in the Reply-To: header |
||
283 | * @return array |
||
284 | */ |
||
285 | public function getReplyTo() |
||
294 | /** |
||
295 | * Set the list of recipients in the Cc: header |
||
296 | * @param mixed An array or a string |
||
297 | */ |
||
298 | View Code Duplication | public function setCc($cc) |
|
310 | /** |
||
311 | * Return the list of recipients in the Cc: header |
||
312 | * @return array |
||
313 | */ |
||
314 | View Code Duplication | public function getCc() |
|
323 | /** |
||
324 | * Set the list of recipients in the Bcc: header |
||
325 | * @param mixed An array or a string |
||
326 | */ |
||
327 | View Code Duplication | public function setBcc($bcc) |
|
339 | /** |
||
340 | * Return the list of recipients in the Bcc: header |
||
341 | * @return array |
||
342 | */ |
||
343 | View Code Duplication | public function getBcc() |
|
352 | /** |
||
353 | * Set the subject in the headers |
||
354 | * @param string The subject of the email |
||
355 | */ |
||
356 | public function setSubject($subject) |
||
360 | /** |
||
361 | * Get the current subject used in the headers |
||
362 | * @return string |
||
363 | */ |
||
364 | public function getSubject() |
||
368 | /** |
||
369 | * Set the date in the headers in RFC 2822 format |
||
370 | * @param int The time as a UNIX timestamp |
||
371 | * @param integer $date |
||
372 | */ |
||
373 | public function setDate($date) |
||
377 | /** |
||
378 | * Get the date as it looks in the headers |
||
379 | * @return integer |
||
380 | */ |
||
381 | public function getDate() |
||
385 | /** |
||
386 | * Set the charset of the document |
||
387 | * @param string The charset used |
||
388 | */ |
||
389 | public function setCharset($charset) |
||
394 | /** |
||
395 | * Get the charset used in the document |
||
396 | * Returns null if none is set |
||
397 | * @return string |
||
398 | */ |
||
399 | public function getCharset() |
||
410 | /** |
||
411 | * Set the "format" attribute to flowed |
||
412 | * @param boolean On or Off |
||
413 | */ |
||
414 | public function setFlowed($flowed=true) |
||
420 | /** |
||
421 | * Check if the message format is set as flowed |
||
422 | * @return boolean |
||
423 | */ |
||
424 | View Code Duplication | public function isFlowed() |
|
433 | /** |
||
434 | * Set the message prioirty in the mail client (don't rely on this) |
||
435 | * @param int The priority as a value between 1 (high) and 5 (low) |
||
436 | */ |
||
437 | public function setPriority($priority) |
||
447 | /** |
||
448 | * Request that the client send back a read-receipt (don't rely on this!) |
||
449 | * @param string Request address |
||
450 | */ |
||
451 | public function requestReadReceipt($request) |
||
467 | /** |
||
468 | * Check if a read receipt has been requested for this message |
||
469 | * @return boolean |
||
470 | */ |
||
471 | public function wantsReadReceipt() |
||
475 | /** |
||
476 | * Get the current message priority |
||
477 | * Returns NULL if none set |
||
478 | * @return string|null |
||
479 | */ |
||
480 | public function getPriority() |
||
485 | /** |
||
486 | * Alias for setData() |
||
487 | * @param mixed Body |
||
488 | */ |
||
489 | public function setBody($body) |
||
493 | /** |
||
494 | * Alias for getData() |
||
495 | * @return string The document body |
||
496 | */ |
||
497 | public function getBody() |
||
501 | /** |
||
502 | * Set the MIME warning message which is displayed to old clients |
||
503 | * @var string The full warning message (in 7bit ascii) |
||
504 | */ |
||
505 | public function setMimeWarning($text) |
||
509 | /** |
||
510 | * Get the MIME warning which is displayed to old clients |
||
511 | * @return string |
||
512 | */ |
||
513 | public function getMimeWarning() |
||
517 | /** |
||
518 | * Attach a mime part or an attachment of some sort |
||
519 | * Any descendant of Swift_Message_Mime can be added safely (including other Swift_Message objects for mail forwarding!!) |
||
520 | * @param Swift_Message_Mime The document to attach |
||
521 | * @param string An identifier to use (one is returned otherwise) |
||
522 | * @return string The identifier for the part |
||
523 | */ |
||
524 | public function attach(Swift_Message_Mime $child, $id=null) |
||
552 | /** |
||
553 | * Remove a nested MIME part |
||
554 | * @param string The ID of the attached part |
||
555 | * @throws Swift_Message_MimeException If no such part exists |
||
556 | */ |
||
557 | public function detach($id) |
||
585 | /** |
||
586 | * Sets the correct content type header by looking at what types of data we have set |
||
587 | */ |
||
588 | protected function fixContentType() |
||
594 | /** |
||
595 | * Move a branch of the tree, containing all it's MIME parts onto another branch |
||
596 | * @param string The content type on the branch itself |
||
597 | * @param string The content type which may exist in the branch's parent |
||
598 | * @param array The array containing all the nodes presently |
||
599 | * @param string The location of the branch now |
||
600 | * @param string The location of the branch after moving |
||
601 | * @param string The key to identify the branch by in it's new location |
||
602 | * @param string $type |
||
603 | * @param string|null $nested_type |
||
604 | * @param string $old_branch |
||
605 | * @param string $new_branch |
||
606 | * @param string $tag |
||
607 | */ |
||
608 | protected function moveBranchIn($type, $nested_type, $from, $old_branch, $new_branch, $tag) |
||
638 | /** |
||
639 | * Analyzes the mixing of MIME types in a mulitpart message an re-arranges if needed |
||
640 | * It looks complicated and long winded but the concept is pretty simple, even if putting it |
||
641 | * in code does me make want to cry! |
||
642 | */ |
||
643 | protected function postAttachFixStructure() |
||
682 | /** |
||
683 | * Move a branch further toward the top of the tree |
||
684 | * @param array The array containing MIME parts from the old branch |
||
685 | * @param string The name of the old branch |
||
686 | * @param string The name of the new branch |
||
687 | * @param string The key of the branch being moved |
||
688 | * @param string $old_branch |
||
689 | * @param string $new_branch |
||
690 | * @param string $tag |
||
691 | */ |
||
692 | protected function moveBranchOut($from, $old_branch, $new_branch, $tag) |
||
719 | /** |
||
720 | * Analyzes the mixing of MIME types in a mulitpart message an re-arranges if needed |
||
721 | * It looks complicated and long winded but the concept is pretty simple, even if putting it |
||
722 | * in code does me make want to cry! |
||
723 | */ |
||
724 | protected function postDetachFixStructure() |
||
774 | /** |
||
775 | * Execute needed logic prior to compilation |
||
776 | */ |
||
777 | public function preBuild() |
||
811 | } |
||
812 |
This check looks for
@param
annotations where the type inferred by our type inference engine differs from the declared type.It makes a suggestion as to what type it considers more descriptive.
Most often this is a case of a parameter that can be null in addition to its declared types.