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 BounceMailHandler 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 BounceMailHandler, and based on these observations, apply Extract Interface, too.
| 1 | <?php |
||
| 55 | class BounceMailHandler |
||
| 56 | { |
||
| 57 | ///////////////////////////////////////////////// |
||
| 58 | // PROPERTIES, PUBLIC |
||
| 59 | ///////////////////////////////////////////////// |
||
| 60 | |||
| 61 | /** |
||
| 62 | * Holds Bounce Mail Handler version. |
||
| 63 | * |
||
| 64 | * @var string |
||
| 65 | */ |
||
| 66 | public $Version = '5.0.0rc1 goffy'; |
||
| 67 | |||
| 68 | /** |
||
| 69 | * Holds result of last processing. |
||
| 70 | * |
||
| 71 | * @var array |
||
| 72 | */ |
||
| 73 | public $result_total = 0; |
||
| 74 | public $result_processed = 0; |
||
| 75 | public $result_unprocessed = 0; |
||
| 76 | public $result_deleted = 0; |
||
| 77 | public $result_moved = 0; |
||
| 78 | |||
| 79 | /** |
||
| 80 | * Mail server |
||
| 81 | * |
||
| 82 | * @var string |
||
| 83 | */ |
||
| 84 | public $mailhost = 'localhost'; |
||
| 85 | |||
| 86 | /** |
||
| 87 | * The username of mailbox |
||
| 88 | * |
||
| 89 | * @var string |
||
| 90 | */ |
||
| 91 | |||
| 92 | public $mailbox_username; |
||
| 93 | /** |
||
| 94 | * The password needed to access mailbox |
||
| 95 | * |
||
| 96 | * @var string |
||
| 97 | */ |
||
| 98 | public $mailbox_password; |
||
| 99 | |||
| 100 | /** |
||
| 101 | * The last error msg |
||
| 102 | * |
||
| 103 | * @var string |
||
| 104 | */ |
||
| 105 | public $error_msg; |
||
| 106 | |||
| 107 | /** |
||
| 108 | * Maximum limit messages processed in one batch |
||
| 109 | * |
||
| 110 | * @var int |
||
| 111 | */ |
||
| 112 | public $max_messages = 3000; |
||
| 113 | |||
| 114 | /** |
||
| 115 | * Callback Action function name |
||
| 116 | * the function that handles the bounce mail. Parameters: |
||
| 117 | * int $msgnum the message number returned by Bounce Mail Handler |
||
| 118 | * string $bounce_type the bounce type: 'antispam','autoreply','concurrent','content_reject','command_reject','internal_error','defer','delayed' => array('remove'=>0,'bounce_type'=>'temporary'),'dns_loop','dns_unknown','full','inactive','latin_only','other','oversize','outofoffice','unknown','unrecognized','user_reject','warning' |
||
| 119 | * string $email the target email address |
||
| 120 | * string $subject the subject, ignore now |
||
| 121 | * string $xheader the XBounceHeader from the mail |
||
| 122 | * 1 or 0 $remove delete status, 0 is not deleted, 1 is deleted |
||
| 123 | * string $rule_no bounce mail detect rule no. |
||
| 124 | * string $rule_cat bounce mail detect rule category |
||
| 125 | * int $totalFetched total number of messages in the mailbox |
||
| 126 | * |
||
| 127 | * @var string |
||
| 128 | */ |
||
| 129 | public $action_function = 'callbackAction'; |
||
| 130 | |||
| 131 | /** |
||
| 132 | * Internal variable |
||
| 133 | * The resource handler for the opened mailbox (POP3/IMAP/NNTP/etc.) |
||
| 134 | * |
||
| 135 | * @var object |
||
| 136 | */ |
||
| 137 | public $_mailbox_link = false; |
||
| 138 | |||
| 139 | /** |
||
| 140 | * Test mode, if true will not delete messages |
||
| 141 | * |
||
| 142 | * @var bool |
||
| 143 | */ |
||
| 144 | public $testmode = false; |
||
| 145 | |||
| 146 | /** |
||
| 147 | * Purge the unknown messages (or not) |
||
| 148 | * |
||
| 149 | * @var bool |
||
| 150 | */ |
||
| 151 | public $purge_unprocessed = false; |
||
| 152 | |||
| 153 | /** |
||
| 154 | * Control the debug output, default is VERBOSE_SIMPLE |
||
| 155 | * |
||
| 156 | * @var int |
||
| 157 | */ |
||
| 158 | public $verbose = VERBOSE_SIMPLE; |
||
| 159 | |||
| 160 | /** |
||
| 161 | * control the failed DSN rules output |
||
| 162 | * |
||
| 163 | * @var bool |
||
| 164 | */ |
||
| 165 | public $debug_dsn_rule = false; |
||
| 166 | |||
| 167 | /** |
||
| 168 | * control the failed BODY rules output |
||
| 169 | * |
||
| 170 | * @var bool |
||
| 171 | */ |
||
| 172 | public $debug_body_rule = false; |
||
| 173 | |||
| 174 | /** |
||
| 175 | * Control the method to process the mail header |
||
| 176 | * if set true, uses the imap_fetchstructure function |
||
| 177 | * otherwise, detect message type directly from headers, |
||
| 178 | * a bit faster than imap_fetchstructure function and take less resources. |
||
| 179 | * however - the difference is negligible |
||
| 180 | * |
||
| 181 | * @var bool |
||
| 182 | */ |
||
| 183 | public $use_fetchstructure = true; |
||
| 184 | |||
| 185 | /** |
||
| 186 | * If disable_delete is equal to true, it will disable the delete function |
||
| 187 | * |
||
| 188 | * @var bool |
||
| 189 | */ |
||
| 190 | public $disable_delete = false; |
||
| 191 | |||
| 192 | /* |
||
| 193 | * Defines new line ending |
||
| 194 | */ |
||
| 195 | public $bmh_newline = "<br>\n"; |
||
| 196 | |||
| 197 | /* |
||
| 198 | * Defines port number, default is '143', other common choices are '110' (pop3), '993' (gmail) |
||
| 199 | * @var integer |
||
| 200 | */ |
||
| 201 | public $port = 143; |
||
| 202 | |||
| 203 | /* |
||
| 204 | * Defines service, default is 'imap', choice includes 'pop3' |
||
| 205 | * @var string |
||
| 206 | */ |
||
| 207 | public $service = 'imap'; |
||
| 208 | |||
| 209 | /* |
||
| 210 | * Defines service option, default is 'notls', other choices are 'tls', 'ssl' |
||
| 211 | * @var string |
||
| 212 | */ |
||
| 213 | public $service_option = 'notls'; |
||
| 214 | |||
| 215 | /* |
||
| 216 | * Mailbox type, default is 'INBOX', other choices are (Tasks, Spam, Replies, etc.) |
||
| 217 | * @var string |
||
| 218 | */ |
||
| 219 | public $boxname = 'INBOX'; |
||
| 220 | |||
| 221 | /* |
||
| 222 | * Determines if soft bounces will be moved to another mailbox folder |
||
| 223 | * @var boolean |
||
| 224 | */ |
||
| 225 | public $moveSoft = false; |
||
| 226 | |||
| 227 | /* |
||
| 228 | * Mailbox folder to move soft bounces to, default is 'soft' |
||
| 229 | * @var string |
||
| 230 | */ |
||
| 231 | public $softMailbox = 'INBOX.soft'; |
||
| 232 | |||
| 233 | /* |
||
| 234 | * Determines if this mail should be moved to softMailbox |
||
| 235 | * @var boolean |
||
| 236 | */ |
||
| 237 | public $moveSoftFlag = false; |
||
| 238 | |||
| 239 | /* |
||
| 240 | * Determines if hard bounces will be moved to another mailbox folder |
||
| 241 | * NOTE: If true, this will disable delete and perform a move operation instead |
||
| 242 | * @var boolean |
||
| 243 | */ |
||
| 244 | public $moveHard = false; |
||
| 245 | |||
| 246 | /* |
||
| 247 | * Mailbox folder to move hard bounces to, default is 'hard' |
||
| 248 | * @var string |
||
| 249 | */ |
||
| 250 | public $hardMailbox = 'INBOX.hard'; |
||
| 251 | |||
| 252 | /* |
||
| 253 | * Determines if this mail should be moved to hardMailbox |
||
| 254 | * @var boolean |
||
| 255 | */ |
||
| 256 | public $moveHardFlag = false; |
||
| 257 | |||
| 258 | /* |
||
| 259 | * Deletes messages globally prior to date in variable |
||
| 260 | * NOTE: excludes any message folder that includes 'sent' in mailbox name |
||
| 261 | * format is same as MySQL: 'yyyy-mm-dd' |
||
| 262 | * if variable is blank, will not process global delete |
||
| 263 | * @var string |
||
| 264 | */ |
||
| 265 | public $deleteMsgDate = ''; |
||
| 266 | |||
| 267 | ///////////////////////////////////////////////// |
||
| 268 | // METHODS |
||
| 269 | ///////////////////////////////////////////////// |
||
| 270 | |||
| 271 | /** |
||
| 272 | * Output additional msg for debug |
||
| 273 | * |
||
| 274 | * @param bool|string $msg , if not given, output the last error msg |
||
| 275 | * @param int $verbose_level , the output level of this message |
||
| 276 | */ |
||
| 277 | public function output($msg = false, $verbose_level = VERBOSE_SIMPLE) |
||
| 286 | |||
| 287 | /** |
||
| 288 | * Open a mail box |
||
| 289 | * |
||
| 290 | * @return bool |
||
| 291 | */ |
||
| 292 | public function openMailbox() |
||
| 323 | |||
| 324 | /** |
||
| 325 | * Open a mail box in local file system |
||
| 326 | * |
||
| 327 | * @param string $file_path (The local mailbox file path) |
||
| 328 | * |
||
| 329 | * @return bool |
||
| 330 | */ |
||
| 331 | public function openLocal($file_path) |
||
| 349 | |||
| 350 | /** |
||
| 351 | * Process the messages in a mailbox |
||
| 352 | * |
||
| 353 | * @param bool|string $max (maximum limit messages processed in one batch, if not given uses the property $max_messages |
||
| 354 | * |
||
| 355 | * @return bool |
||
| 356 | */ |
||
| 357 | public function processMailbox($max = false) |
||
| 499 | |||
| 500 | /** |
||
| 501 | * Function to determine if a particular value is found in a imap_fetchstructure key |
||
| 502 | * |
||
| 503 | * @param array $currParameters (imap_fetstructure parameters) |
||
| 504 | * @param string $varKey (imap_fetstructure key) |
||
| 505 | * @param string $varValue (value to check for) |
||
| 506 | * |
||
| 507 | * @return bool |
||
| 508 | */ |
||
| 509 | public function isParameter($currParameters, $varKey, $varValue) |
||
| 521 | |||
| 522 | /** |
||
| 523 | * Function to process each individual message |
||
| 524 | * |
||
| 525 | * @param int $pos (message number) |
||
| 526 | * @param string $type (DNS or BODY type) |
||
| 527 | * @param string $totalFetched (total number of messages in mailbox) |
||
| 528 | * |
||
| 529 | * @return bool |
||
| 530 | */ |
||
| 531 | public function processBounce($pos, $type, $totalFetched) |
||
| 644 | |||
| 645 | /** |
||
| 646 | * Function to check if a mailbox exists |
||
| 647 | * - if not found, it will create it |
||
| 648 | * |
||
| 649 | * @param string $mailbox (the mailbox name, must be in 'INBOX.checkmailbox' format) |
||
| 650 | * @param bool $create (whether or not to create the checkmailbox if not found, defaults to true) |
||
| 651 | * |
||
| 652 | * @return null|bool |
||
| 653 | */ |
||
| 654 | public function mailbox_exist($mailbox, $create = true) |
||
| 690 | |||
| 691 | /** |
||
| 692 | * Function to delete messages in a mailbox, based on date |
||
| 693 | * NOTE: this is global ... will affect all mailboxes except any that have 'sent' in the mailbox name |
||
| 694 | * |
||
| 695 | * @internal param string $mailbox (the mailbox name) |
||
| 696 | */ |
||
| 697 | public function globalDelete() |
||
| 731 | } |
||
| 732 |
Our type inference engine has found an assignment to a property that is incompatible with the declared type of that property.
Either this assignment is in error or the assigned type should be added to the documentation/type hint for that property..