Complex classes like Mailer 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 Mailer, and based on these observations, apply Extract Interface, too.
| 1 | <?php |
||
| 14 | class Mailer extends Object |
||
| 15 | { |
||
| 16 | |||
| 17 | /** |
||
| 18 | * Default encoding type for messages. Available options are: |
||
| 19 | * - quoted-printable |
||
| 20 | * - base64 |
||
| 21 | * |
||
| 22 | * @var string |
||
| 23 | * @config |
||
| 24 | */ |
||
| 25 | private static $default_message_encoding = 'quoted-printable'; |
||
| 26 | |||
| 27 | /** |
||
| 28 | * Encoding type currently set |
||
| 29 | * |
||
| 30 | * @var string |
||
| 31 | */ |
||
| 32 | protected $messageEncoding = null; |
||
| 33 | |||
| 34 | /** |
||
| 35 | * Email used for bounces |
||
| 36 | * |
||
| 37 | * @var string |
||
| 38 | * @config |
||
| 39 | */ |
||
| 40 | private static $default_bounce_email = null; |
||
| 41 | |||
| 42 | /** |
||
| 43 | * Email used for bounces |
||
| 44 | * |
||
| 45 | * @var string |
||
| 46 | */ |
||
| 47 | protected $bounceEmail = null; |
||
| 48 | |||
| 49 | /** |
||
| 50 | * Email used for bounces |
||
| 51 | * |
||
| 52 | * @return string |
||
| 53 | */ |
||
| 54 | public function getBounceEmail() |
||
| 60 | |||
| 61 | /** |
||
| 62 | * Set the email used for bounces |
||
| 63 | * |
||
| 64 | * @param string $email |
||
| 65 | */ |
||
| 66 | public function setBounceEmail($email) |
||
| 70 | |||
| 71 | /** |
||
| 72 | * Get the encoding type used for plain text messages |
||
| 73 | * |
||
| 74 | * @return string |
||
| 75 | */ |
||
| 76 | public function getMessageEncoding() |
||
| 80 | |||
| 81 | /** |
||
| 82 | * Sets encoding type for messages. Available options are: |
||
| 83 | * - quoted-printable |
||
| 84 | * - base64 |
||
| 85 | * |
||
| 86 | * @param string $encoding |
||
| 87 | */ |
||
| 88 | public function setMessageEncoding($encoding) |
||
| 92 | |||
| 93 | /** |
||
| 94 | * Encode a message using the given encoding mechanism |
||
| 95 | * |
||
| 96 | * @param string $message |
||
| 97 | * @param string $encoding |
||
| 98 | * @return string Encoded $message |
||
| 99 | */ |
||
| 100 | protected function encodeMessage($message, $encoding) |
||
| 111 | |||
| 112 | /** |
||
| 113 | * Merge custom headers with default ones |
||
| 114 | * |
||
| 115 | * @param array $headers Default headers |
||
| 116 | * @param array $customHeaders Custom headers |
||
| 117 | * @return array Resulting message headers |
||
| 118 | */ |
||
| 119 | protected function mergeCustomHeaders($headers, $customHeaders) |
||
| 141 | |||
| 142 | /** |
||
| 143 | * Send a plain-text email. |
||
| 144 | * |
||
| 145 | * @param string $to Email recipient |
||
| 146 | * @param string $from Email from |
||
| 147 | * @param string $subject Subject text |
||
| 148 | * @param string $plainContent Plain text content |
||
| 149 | * @param array $attachedFiles List of attached files |
||
| 150 | * @param array $customHeaders List of custom headers |
||
| 151 | * @return mixed Return false if failure, or list of arguments if success |
||
| 152 | */ |
||
| 153 | public function sendPlain($to, $from, $subject, $plainContent, $attachedFiles = array(), $customHeaders = array()) |
||
| 163 | |||
| 164 | |||
| 165 | /** |
||
| 166 | * Sends an email as a both HTML and plaintext |
||
| 167 | * |
||
| 168 | * @param string $to Email recipient |
||
| 169 | * @param string $from Email from |
||
| 170 | * @param string $subject Subject text |
||
| 171 | * @param string $htmlContent HTML Content |
||
| 172 | * @param array $attachedFiles List of attachments |
||
| 173 | * @param array $customHeaders User specified headers |
||
| 174 | * @param string $plainContent Plain text content. If omitted, will be generated from $htmlContent |
||
| 175 | * @return mixed Return false if failure, or list of arguments if success |
||
| 176 | */ |
||
| 177 | public function sendHTML( |
||
| 197 | |||
| 198 | /** |
||
| 199 | * Send an email of an arbitrary format |
||
| 200 | * |
||
| 201 | * @param string $to To |
||
| 202 | * @param string $from From |
||
| 203 | * @param string $subject Subject |
||
| 204 | * @param array $attachedFiles List of attachments |
||
| 205 | * @param array $customHeaders User specified headers |
||
| 206 | * @param string $fullBody Prepared message |
||
| 207 | * @param array $headers Prepared headers |
||
| 208 | * @return mixed Return false if failure, or list of arguments if success |
||
| 209 | */ |
||
| 210 | protected function sendPreparedMessage($to, $from, $subject, $attachedFiles, $customHeaders, $fullBody, $headers) |
||
| 235 | |||
| 236 | /** |
||
| 237 | * Send the actual email |
||
| 238 | * |
||
| 239 | * @param string $to |
||
| 240 | * @param string $subjectEncoded |
||
| 241 | * @param string $fullBody |
||
| 242 | * @param string $headersEncoded |
||
| 243 | * @param string $bounceAddress |
||
| 244 | * @return mixed Return false if failure, or list of arguments if success |
||
| 245 | */ |
||
| 246 | protected function email($to, $subjectEncoded, $fullBody, $headersEncoded, $bounceAddress) |
||
| 260 | |||
| 261 | /** |
||
| 262 | * Encode attachments into a message |
||
| 263 | * |
||
| 264 | * @param array $attachments |
||
| 265 | * @param array $headers |
||
| 266 | * @param string $body |
||
| 267 | * @return array Array containing completed body followed by headers |
||
| 268 | */ |
||
| 269 | protected function encodeAttachments($attachments, $headers, $body) |
||
| 287 | |||
| 288 | /** |
||
| 289 | * Generate the plainPart of a html message |
||
| 290 | * |
||
| 291 | * @param string $plainContent Plain body |
||
| 292 | * @param string $htmlContent HTML message |
||
| 293 | * @return string Encoded headers / message in a single block |
||
| 294 | */ |
||
| 295 | protected function preparePlainSubmessage($plainContent, $htmlContent) |
||
| 312 | |||
| 313 | /** |
||
| 314 | * Generate the html part of a html message |
||
| 315 | * |
||
| 316 | * @param string $htmlContent HTML message |
||
| 317 | * @return string Encoded headers / message in a single block |
||
| 318 | */ |
||
| 319 | protected function prepareHTMLSubmessage($htmlContent) |
||
| 343 | |||
| 344 | /** |
||
| 345 | * Encode an array of parts using multipart |
||
| 346 | * |
||
| 347 | * @param array $parts List of parts |
||
| 348 | * @param string $contentType Content-type of parts |
||
| 349 | * @param array $headers Existing headers to include in response |
||
| 350 | * @return array Array with two items, the body followed by headers |
||
| 351 | */ |
||
| 352 | protected function encodeMultipart($parts, $contentType, $headers = array()) |
||
| 376 | |||
| 377 | |||
| 378 | /** |
||
| 379 | * Add headers to the start of the message |
||
| 380 | * |
||
| 381 | * @param array $headers |
||
| 382 | * @param string $body |
||
| 383 | * @return string Resulting message body |
||
| 384 | */ |
||
| 385 | protected function processHeaders($headers, $body = '') |
||
| 397 | |||
| 398 | /** |
||
| 399 | * Encode the contents of a file for emailing, including headers |
||
| 400 | * |
||
| 401 | * $file can be an array, in which case it expects these members: |
||
| 402 | * 'filename' - the filename of the file |
||
| 403 | * 'contents' - the raw binary contents of the file as a string |
||
| 404 | * and can optionally include these members: |
||
| 405 | * 'mimetype' - the mimetype of the file (calculated from filename if missing) |
||
| 406 | * 'contentLocation' - the 'Content-Location' header value for the file |
||
| 407 | * |
||
| 408 | * $file can also be a string, in which case it is assumed to be the filename |
||
| 409 | * |
||
| 410 | * h5. contentLocation |
||
| 411 | * |
||
| 412 | * Content Location is one of the two methods allowed for embedding images into an html email. |
||
| 413 | * It's also the simplest, and best supported. |
||
| 414 | * |
||
| 415 | * Assume we have an email with this in the body: |
||
| 416 | * |
||
| 417 | * <img src="http://example.com/image.gif" /> |
||
| 418 | * |
||
| 419 | * To display the image, an email viewer would have to download the image from the web every time |
||
| 420 | * it is displayed. Due to privacy issues, most viewers will not display any images unless |
||
| 421 | * the user clicks 'Show images in this email'. Not optimal. |
||
| 422 | * |
||
| 423 | * However, we can also include a copy of this image as an attached file in the email. |
||
| 424 | * By giving it a contentLocation of "http://example.com/image.gif" most email viewers |
||
| 425 | * will use this attached copy instead of downloading it. Better, |
||
| 426 | * most viewers will show it without a 'Show images in this email' conformation. |
||
| 427 | * |
||
| 428 | * Here is an example of passing this information through Email.php: |
||
| 429 | * |
||
| 430 | * $email = new Email(); |
||
| 431 | * $email->attachments[] = array( |
||
| 432 | * 'filename' => BASE_PATH . "/themes/mytheme/images/header.gif", |
||
| 433 | * 'contents' => file_get_contents(BASE_PATH . "/themes/mytheme/images/header.gif"), |
||
| 434 | * 'mimetype' => 'image/gif', |
||
| 435 | * 'contentLocation' => Director::absoluteBaseURL() . "/themes/mytheme/images/header.gif" |
||
| 436 | * ); |
||
| 437 | * |
||
| 438 | * @param array|string $file |
||
| 439 | * @param bool $destFileName |
||
| 440 | * @param string $disposition |
||
| 441 | * @param string $extraHeaders |
||
| 442 | * @return string |
||
| 443 | */ |
||
| 444 | protected function encodeFileForEmail($file, $destFileName = false, $disposition = null, $extraHeaders = "") |
||
| 501 | |||
| 502 | /** |
||
| 503 | * Cleans up emails which may be in 'Name <[email protected]>' format |
||
| 504 | * |
||
| 505 | * @param string $emailAddress |
||
| 506 | * @return string |
||
| 507 | */ |
||
| 508 | protected function validEmailAddress($emailAddress) |
||
| 527 | } |
||
| 528 |
Adding an explicit array definition is generally preferable to implicit array definition as it guarantees a stable state of the code.
Let’s take a look at an example:
As you can see in this example, the array
$myArrayis initialized the first time when the foreach loop is entered. You can also see that the value of thebarkey is only written conditionally; thus, its value might result from a previous iteration.This might or might not be intended. To make your intention clear, your code more readible and to avoid accidental bugs, we recommend to add an explicit initialization $myArray = array() either outside or inside the foreach loop.