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 Client 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 Client, and based on these observations, apply Extract Interface, too.
| 1 | <?php |
||
| 15 | class Client extends \GuzzleHttp\Client |
||
| 16 | { |
||
| 17 | /** |
||
| 18 | * @const string Version number |
||
| 19 | */ |
||
| 20 | const VERSION = '0.0.1'; |
||
| 21 | |||
| 22 | /** |
||
| 23 | * Defaults to expecting that Apache Tomcat runs on port 8080 on localhost |
||
| 24 | * (127.0.0.1). |
||
| 25 | * |
||
| 26 | * @var array |
||
| 27 | */ |
||
| 28 | protected $options = [ |
||
| 29 | 'scheme' => 'https', |
||
| 30 | 'hostname' => 'localhost', |
||
| 31 | 'port' => '8080', |
||
| 32 | 'token' => null, |
||
| 33 | 'username' => null, |
||
| 34 | 'password' => null, |
||
| 35 | ]; |
||
| 36 | |||
| 37 | /** |
||
| 38 | * @param array $options |
||
| 39 | */ |
||
| 40 | 20 | public function __construct($options = []) |
|
| 63 | |||
| 64 | /** |
||
| 65 | * Set the bearer token. |
||
| 66 | * |
||
| 67 | * @param string $token Bearer Token from Auth request |
||
| 68 | */ |
||
| 69 | 11 | public function setBearerToken($token) |
|
| 73 | |||
| 74 | /** |
||
| 75 | * Authenticate and get Bearer token from SmartCall. |
||
| 76 | * |
||
| 77 | * @param string $username |
||
| 78 | * @param string $password |
||
| 79 | * |
||
| 80 | * @throws Exception |
||
| 81 | * |
||
| 82 | * @return array |
||
| 83 | */ |
||
| 84 | 3 | public function auth($username, $password) |
|
| 85 | { |
||
| 86 | try { |
||
| 87 | 3 | $response = $this->post( |
|
| 88 | 3 | '/webservice/auth', |
|
| 89 | [ |
||
| 90 | 'headers' => [ |
||
| 91 | 3 | 'Authorization' => sprintf( |
|
| 92 | 3 | 'Basic %s', |
|
| 93 | 3 | base64_encode( |
|
| 94 | 3 | sprintf( |
|
| 95 | 3 | '%s:%s', |
|
| 96 | 3 | $username, |
|
| 97 | 3 | $password |
|
| 98 | ) |
||
| 99 | ) |
||
| 100 | ), |
||
| 101 | ], |
||
| 102 | ] |
||
| 103 | ); |
||
| 104 | |||
| 105 | return [ |
||
| 106 | 1 | 'status' => 'ok', |
|
| 107 | 1 | 'http_code' => $response->getStatusCode(), |
|
| 108 | 1 | 'body' => (string) $response->getBody(), |
|
| 109 | ]; |
||
| 110 | 2 | } catch (\GuzzleHttp\Exception\ClientException $e) { |
|
| 111 | 2 | return $this->clientError($e); |
|
| 112 | } catch (\GuzzleHttp\Exception\ServerException $e) { |
||
| 113 | return $this->parseError($e); |
||
| 114 | } |
||
| 115 | } |
||
| 116 | |||
| 117 | /** |
||
| 118 | * Authenticate and invalidates all the user allocated tokens. |
||
| 119 | * |
||
| 120 | * @throws Exception |
||
| 121 | * |
||
| 122 | * @return array |
||
| 123 | */ |
||
| 124 | 2 | View Code Duplication | public function authDelete() |
| 150 | |||
| 151 | /** |
||
| 152 | * Authenticate and invalidates all the user allocated tokens. |
||
| 153 | * |
||
| 154 | * @param string $username |
||
| 155 | * @param string $password |
||
| 156 | * |
||
| 157 | * @throws Exception |
||
| 158 | * |
||
| 159 | * @return array |
||
| 160 | */ |
||
| 161 | 3 | View Code Duplication | public function authFlush($username = null, $password = null) |
| 184 | |||
| 185 | /** |
||
| 186 | * Authenticate and gets the number of available session tokens. |
||
| 187 | * |
||
| 188 | * @param string $username |
||
| 189 | * @param string $password |
||
| 190 | * |
||
| 191 | * @throws Exception |
||
| 192 | * |
||
| 193 | * @return array |
||
| 194 | */ |
||
| 195 | 3 | View Code Duplication | public function authToken($username = null, $password = null) |
| 218 | |||
| 219 | /** |
||
| 220 | * Authenticate and request period based cashup reports. |
||
| 221 | * |
||
| 222 | * @param string $dealerMsisdn |
||
| 223 | * @param string $start |
||
| 224 | * @param string $end |
||
| 225 | * |
||
| 226 | * @throws Exception |
||
| 227 | * |
||
| 228 | * @return array |
||
| 229 | */ |
||
| 230 | View Code Duplication | public function cashup($dealerMsisdn, $start, $end) |
|
| 261 | |||
| 262 | /** |
||
| 263 | * Authenticate and retrieves the dealer balance in Rands. |
||
| 264 | * |
||
| 265 | * @param string $dealerMsisdn |
||
| 266 | * |
||
| 267 | * @throws Exception |
||
| 268 | * |
||
| 269 | * @return array |
||
| 270 | */ |
||
| 271 | View Code Duplication | public function balance($dealerMsisdn) |
|
| 300 | /** |
||
| 301 | * Authenticate and request current day cashup report. |
||
| 302 | * |
||
| 303 | * @param string $dealerMsisdn |
||
| 304 | * |
||
| 305 | * @throws Exception |
||
| 306 | * |
||
| 307 | * @return array |
||
| 308 | */ |
||
| 309 | View Code Duplication | public function cashupToday($dealerMsisdn) |
|
| 338 | |||
| 339 | /** |
||
| 340 | * Authenticate and request to transfer funds from one Smartload account to another. |
||
| 341 | * |
||
| 342 | * @param string $fromDealerMsisdn |
||
| 343 | * @param string $toDealerMsisdn |
||
| 344 | * @param string $amount |
||
| 345 | * @param string $sendSms |
||
| 346 | * |
||
| 347 | * @throws Exception |
||
| 348 | * |
||
| 349 | * @return array |
||
| 350 | */ |
||
| 351 | View Code Duplication | public function fundstransfer($fromDealerMsisdn, $toDealerMsisdn, $amount, $sendSms) |
|
| 383 | |||
| 384 | /** |
||
| 385 | * Authenticate and retrieves a list of all available networks. |
||
| 386 | * |
||
| 387 | * @throws Exception |
||
| 388 | * |
||
| 389 | * @return array |
||
| 390 | */ |
||
| 391 | 2 | View Code Duplication | public function network($id) |
| 420 | |||
| 421 | /** |
||
| 422 | * Authenticate and retrieves a list of all available networks. |
||
| 423 | * |
||
| 424 | * @throws Exception |
||
| 425 | * |
||
| 426 | * @return array |
||
| 427 | */ |
||
| 428 | 2 | View Code Duplication | public function networks() |
| 454 | |||
| 455 | /** |
||
| 456 | * Test SmartCall is responding. |
||
| 457 | * |
||
| 458 | * @throws Exception |
||
| 459 | * |
||
| 460 | * @return array |
||
| 461 | */ |
||
| 462 | 1 | public function ping() |
|
| 480 | |||
| 481 | /** |
||
| 482 | * Authenticate and retrieves a list of all available networks. |
||
| 483 | * |
||
| 484 | * @throws Exception |
||
| 485 | * |
||
| 486 | * @return array |
||
| 487 | */ |
||
| 488 | 2 | View Code Duplication | public function products($id) |
| 517 | |||
| 518 | /** |
||
| 519 | * Authenticate and checks if the provided ID (MSISDN) is registered with Smartload. |
||
| 520 | * |
||
| 521 | * @param string $dealerMsisdn |
||
| 522 | * |
||
| 523 | * @throws Exception |
||
| 524 | * |
||
| 525 | * @return array |
||
| 526 | */ |
||
| 527 | View Code Duplication | public function registered($dealerMsisdn) |
|
| 556 | |||
| 557 | /** |
||
| 558 | * Parse the java exception that we receive from Smartcall's Tomcat's. |
||
| 559 | * |
||
| 560 | * @param \GuzzleHttp\Exception\ClientException $exception |
||
| 561 | * |
||
| 562 | * @return array |
||
| 563 | */ |
||
| 564 | 9 | View Code Duplication | private function clientError(\GuzzleHttp\Exception\ClientException $exception) |
| 574 | |||
| 575 | /** |
||
| 576 | * Parse the java exception that we receive from Smartcall's Tomcat's. |
||
| 577 | * |
||
| 578 | * @param \GuzzleHttp\Exception\ServerException $exception |
||
| 579 | * |
||
| 580 | * @return array |
||
| 581 | */ |
||
| 582 | View Code Duplication | private function parseError(\GuzzleHttp\Exception\ServerException $exception) |
|
| 593 | |||
| 594 | /** |
||
| 595 | * Use basic authentication header content if bearer token is not set. |
||
| 596 | * |
||
| 597 | * @param string $username |
||
| 598 | * @param string $password |
||
| 599 | * |
||
| 600 | * @return string |
||
| 601 | */ |
||
| 602 | 6 | private function bearerOrBasic($username = null, $password = null) |
|
| 622 | } |
||
| 623 |
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.