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
@paramannotations 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.