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 Httprequest 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 Httprequest, and based on these observations, apply Extract Interface, too.
1 | <?php namespace Comodojo\Httprequest; |
||
24 | class Httprequest { |
||
25 | |||
26 | /** |
||
27 | * Remote host address (complete url) |
||
28 | * |
||
29 | * @var string |
||
30 | */ |
||
31 | private $address = null; |
||
32 | |||
33 | /** |
||
34 | * Remote host port |
||
35 | * |
||
36 | * @var integer |
||
37 | */ |
||
38 | private $port = 80; |
||
39 | |||
40 | /** |
||
41 | * Conversation method (GET or POST) |
||
42 | * |
||
43 | * @var string |
||
44 | */ |
||
45 | private $method = 'GET'; |
||
46 | |||
47 | /** |
||
48 | * Timeout for request, in seconds. |
||
49 | * |
||
50 | * @var integer |
||
51 | */ |
||
52 | private $timeout = 30; |
||
53 | |||
54 | /** |
||
55 | * HTTP Version (1.0/1.1) |
||
56 | * |
||
57 | * @var string |
||
58 | */ |
||
59 | private $httpVersion = "1.0"; |
||
60 | |||
61 | /** |
||
62 | * Auth method to use. It currently support only: |
||
63 | * - BASIC |
||
64 | * - NTLM (only if CURL is available) |
||
65 | * |
||
66 | * @var string |
||
67 | */ |
||
68 | private $authenticationMethod = null; |
||
69 | |||
70 | /** |
||
71 | * Remote host auth username |
||
72 | * |
||
73 | * @var string |
||
74 | */ |
||
75 | private $user = null; |
||
76 | |||
77 | /** |
||
78 | * Remote host auth password |
||
79 | * |
||
80 | * @var string |
||
81 | */ |
||
82 | private $pass = null; |
||
83 | |||
84 | /** |
||
85 | * Request user agent |
||
86 | * |
||
87 | * @var string |
||
88 | */ |
||
89 | private $userAgent = 'Comodojo-Httprequest'; |
||
90 | |||
91 | /** |
||
92 | * Content type |
||
93 | * |
||
94 | * @var string |
||
95 | */ |
||
96 | private $contentType = 'application/x-www-form-urlencoded'; |
||
97 | |||
98 | /** |
||
99 | * array of headers to send |
||
100 | * |
||
101 | * @var array |
||
102 | */ |
||
103 | private $headers = array( |
||
104 | 'Accept' => 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8', |
||
105 | 'Accept-Language' => 'en-us,en;q=0.5', |
||
106 | 'Accept-Encoding' => 'gzip,deflate', |
||
107 | 'Accept-Charset' => 'UTF-8;q=0.7,*;q=0.7' |
||
108 | ); |
||
109 | |||
110 | /** |
||
111 | * Should we use a proxy? |
||
112 | * |
||
113 | * @var string |
||
114 | */ |
||
115 | private $proxy = null; |
||
116 | |||
117 | private $proxy_auth = null; |
||
118 | |||
119 | /** |
||
120 | * Allowed HTTP methods |
||
121 | * |
||
122 | * @var array |
||
123 | */ |
||
124 | private $supported_auth_methods = array("BASIC", "DIGEST", "SPNEGO", "NTLM"); |
||
125 | |||
126 | /** |
||
127 | * Allowed HTTP authentication |
||
128 | * |
||
129 | * @var array |
||
130 | */ |
||
131 | private $supported_http_methods = array("GET", "POST", "PUT", "DELETE"); |
||
132 | |||
133 | /** |
||
134 | * Are we using curl? |
||
135 | */ |
||
136 | private $curl = true; |
||
137 | |||
138 | /** |
||
139 | * Received headers |
||
140 | * |
||
141 | * @var array |
||
142 | */ |
||
143 | private $receivedHeaders = array(); |
||
144 | |||
145 | /** |
||
146 | * Received http status code |
||
147 | * |
||
148 | * @var int |
||
149 | */ |
||
150 | private $receivedHttpStatus = null; |
||
151 | |||
152 | /** |
||
153 | * Transfer channel |
||
154 | * |
||
155 | * @var resource |
||
156 | */ |
||
157 | private $ch = false; |
||
158 | |||
159 | private $stream_get_data = null; |
||
160 | |||
161 | /** |
||
162 | * Ignore Errors (stream only) |
||
163 | * |
||
164 | * @var boolean |
||
165 | */ |
||
166 | private $ignore_errors = false; |
||
167 | |||
168 | /** |
||
169 | * Class constructor |
||
170 | * |
||
171 | * @param string $address Remote host address |
||
172 | * @param bool $curl Use curl (true) or stream (false) |
||
173 | * |
||
174 | * @throws \Comodojo\Exception\HttpException |
||
175 | */ |
||
176 | 84 | final public function __construct($address = false, $curl = true) { |
|
195 | |||
196 | /** |
||
197 | * Class destructor |
||
198 | * |
||
199 | */ |
||
200 | 6 | final public function __destruct() { |
|
205 | |||
206 | /** |
||
207 | * Set remote host address |
||
208 | * |
||
209 | * @param string $address Remote host address |
||
210 | * |
||
211 | * @return \Comodojo\Httprequest\Httprequest |
||
212 | * |
||
213 | * @throws \Comodojo\Exception\HttpException |
||
214 | */ |
||
215 | 84 | final public function setHost($address) { |
|
226 | |||
227 | /** |
||
228 | * Force lib to use curl (default if available) or stream |
||
229 | * |
||
230 | * @param bool $mode Use curl (true) or stream (false) |
||
231 | * |
||
232 | * @return \Comodojo\Httprequest\Httprequest |
||
233 | */ |
||
234 | 84 | final public function setCurl($mode = true) { |
|
244 | |||
245 | /** |
||
246 | * Set http authentication |
||
247 | * |
||
248 | * @param string $method Auth method (BASIC or NTLM) |
||
249 | * @param string $user Username to use |
||
250 | * @param string $pass User password |
||
251 | * |
||
252 | * @return \Comodojo\Httprequest\Httprequest |
||
253 | * |
||
254 | * @throws \Comodojo\Exception\HttpException |
||
255 | */ |
||
256 | 9 | final public function setAuth($method, $user, $pass = null) { |
|
280 | |||
281 | /** |
||
282 | * Set user agent for request |
||
283 | * |
||
284 | * @param string $ua User Agent |
||
285 | * |
||
286 | * @return \Comodojo\Httprequest\Httprequest |
||
287 | * |
||
288 | * @throws \Comodojo\Exception\HttpException |
||
289 | */ |
||
290 | 9 | final public function setUserAgent($ua) { |
|
299 | |||
300 | /** |
||
301 | * Set connection timeout |
||
302 | * |
||
303 | * @param int $sec Timeout to wait for (in second) |
||
304 | * |
||
305 | * @return \Comodojo\Httprequest\Httprequest |
||
306 | */ |
||
307 | 9 | final public function setTimeout($sec) { |
|
316 | |||
317 | /** |
||
318 | * Set http version (1.0/1.1) |
||
319 | * |
||
320 | * @param string $ver 1.0 or 1.1 |
||
321 | * |
||
322 | * @return \Comodojo\Httprequest\Httprequest |
||
323 | */ |
||
324 | 3 | final public function setHttpVersion($ver) { |
|
339 | |||
340 | /** |
||
341 | * Set http content type |
||
342 | * |
||
343 | * @param string $type |
||
344 | * |
||
345 | * @return \Comodojo\Httprequest\Httprequest |
||
346 | * |
||
347 | * @throws \Comodojo\Exception\HttpException |
||
348 | */ |
||
349 | 9 | final public function setContentType($type) { |
|
358 | |||
359 | /** |
||
360 | * Set TCP port to connect to |
||
361 | * |
||
362 | * @param integer $port TCP port (default 80) |
||
363 | * |
||
364 | * @return \Comodojo\Httprequest\Httprequest |
||
365 | */ |
||
366 | 3 | final public function setPort($port) { |
|
379 | |||
380 | /** |
||
381 | * Set HTTP method to use |
||
382 | * |
||
383 | * @param string $method HTTP METHOD |
||
384 | * |
||
385 | * @return \Comodojo\Httprequest\Httprequest |
||
386 | * |
||
387 | * @throws \Comodojo\Exception\HttpException |
||
388 | */ |
||
389 | 27 | final public function setHttpMethod($method) { |
|
404 | |||
405 | /** |
||
406 | * Set whether or not to ignore errors |
||
407 | * |
||
408 | * @param boolean $ignore Should stream ignore errors |
||
409 | * |
||
410 | * @return \Comodojo\Httprequest\Httprequest |
||
411 | */ |
||
412 | final public function setIgnoreErrors($ignore = true) { |
||
419 | |||
420 | /** |
||
421 | * Set HTTP method to use |
||
422 | * |
||
423 | * @param string $address Proxy URL or IP address |
||
424 | * @param string $user (optional) User name for proy auth |
||
425 | * @param string $pass (optional) User password for proxy auth |
||
426 | * |
||
427 | * @return \Comodojo\Httprequest\Httprequest |
||
428 | * |
||
429 | * @throws \Comodojo\Exception\HttpException |
||
430 | */ |
||
431 | 3 | final public function setProxy($address, $user = null, $pass = null) { |
|
452 | |||
453 | /** |
||
454 | * Set header component |
||
455 | * |
||
456 | * @param string $header Header name |
||
457 | * @param string $value Header content (optional) |
||
458 | * |
||
459 | * @return \Comodojo\Httprequest\Httprequest |
||
460 | */ |
||
461 | 27 | final public function setHeader($header, $value = NULL) { |
|
468 | |||
469 | /** |
||
470 | * Unset header component |
||
471 | * |
||
472 | * @param string $header Header name |
||
473 | * |
||
474 | * @return \Comodojo\Httprequest\Httprequest |
||
475 | */ |
||
476 | final public function unsetHeader($header) { |
||
483 | |||
484 | /** |
||
485 | * Get the whole headers array |
||
486 | * |
||
487 | * @return array |
||
488 | */ |
||
489 | 78 | final public function getHeaders() { |
|
494 | |||
495 | /** |
||
496 | * Get received headers |
||
497 | * |
||
498 | * @return array |
||
499 | */ |
||
500 | 24 | final public function getReceivedHeaders() { |
|
505 | |||
506 | /** |
||
507 | * Get received headers |
||
508 | * |
||
509 | * @return integer |
||
510 | */ |
||
511 | 60 | final public function getHttpStatusCode() { |
|
516 | |||
517 | /** |
||
518 | * Get transport channel (curl channel or stream context) |
||
519 | * |
||
520 | * @return mixed |
||
521 | */ |
||
522 | 6 | final public function getChannel() { |
|
527 | |||
528 | /** |
||
529 | * Init transport and send data to the remote host. |
||
530 | * |
||
531 | * @return string |
||
532 | * |
||
533 | * @throws \Comodojo\Exception\HttpException |
||
534 | */ |
||
535 | 30 | View Code Duplication | public function send($data = null) { |
563 | |||
564 | /** |
||
565 | * Init transport and get remote content |
||
566 | * |
||
567 | * @return string |
||
568 | * |
||
569 | * @throws \Comodojo\Exception\HttpException |
||
570 | */ |
||
571 | 48 | View Code Duplication | public function get() { |
598 | |||
599 | /** |
||
600 | * Reset the data channel for new request |
||
601 | * |
||
602 | */ |
||
603 | final public function reset() { |
||
645 | |||
646 | /** |
||
647 | * Parse a single header |
||
648 | * |
||
649 | * @param string $header |
||
650 | * @param string $value |
||
651 | * |
||
652 | * @return string |
||
653 | */ |
||
654 | private function parseHeader($header, $value) { |
||
661 | |||
662 | /** |
||
663 | * Init the CURL channel |
||
664 | * |
||
665 | * @param string $data |
||
666 | * |
||
667 | * @throws \Comodojo\Exception\HttpException |
||
668 | */ |
||
669 | 39 | private function init_curl($data) { |
|
809 | |||
810 | /** |
||
811 | * Init the STREAM channel |
||
812 | * |
||
813 | * @param string $data |
||
814 | * |
||
815 | * @throws \Comodojo\Exception\HttpException |
||
816 | */ |
||
817 | 39 | private function init_stream($data) { |
|
884 | |||
885 | /** |
||
886 | * Send data via CURL |
||
887 | * |
||
888 | * @return string |
||
889 | * |
||
890 | * @throws \Comodojo\Exception\HttpException |
||
891 | */ |
||
892 | 39 | private function send_curl() { |
|
915 | |||
916 | /** |
||
917 | * Send data via STREAM |
||
918 | * |
||
919 | * @return string |
||
920 | * |
||
921 | * @throws \Comodojo\Exception\HttpException |
||
922 | */ |
||
923 | 39 | private function send_stream() { |
|
974 | |||
975 | /** |
||
976 | * Tokenize received headers |
||
977 | * |
||
978 | * @param string $headers |
||
979 | * |
||
980 | * @return array |
||
981 | */ |
||
982 | 72 | private static function tokenizeHeaders($headers) { |
|
1003 | |||
1004 | /** |
||
1005 | * Close transport layer |
||
1006 | */ |
||
1007 | private function close_transport() { |
||
1016 | |||
1017 | } |
||
1018 |
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.