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