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 |
||
| 35 | class Client extends ApiCall |
||
| 36 | { |
||
| 37 | /** |
||
| 38 | * @var SessionStorage |
||
| 39 | */ |
||
| 40 | private $session; |
||
| 41 | |||
| 42 | /** |
||
| 43 | * @var Http\IRequest |
||
| 44 | */ |
||
| 45 | private $httpRequest; |
||
| 46 | |||
| 47 | /** |
||
| 48 | * The ID of the Twitter user, or 0 if the user is logged out |
||
| 49 | * |
||
| 50 | * @var integer |
||
| 51 | */ |
||
| 52 | private $user; |
||
| 53 | |||
| 54 | /** |
||
| 55 | * The OAuth access token received in exchange for a valid authorization code |
||
| 56 | * null means the access token has yet to be determined |
||
| 57 | * |
||
| 58 | * @var OAuth\Token |
||
| 59 | */ |
||
| 60 | private $accessToken; |
||
| 61 | |||
| 62 | /** |
||
| 63 | * @param OAuth\Consumer $consumer |
||
| 64 | * @param OAuth\HttpClient $httpClient |
||
| 65 | * @param Configuration $config |
||
| 66 | * @param SessionStorage $session |
||
| 67 | * @param Http\IRequest $httpRequest |
||
| 68 | */ |
||
| 69 | public function __construct( |
||
| 70 | OAuth\Consumer $consumer, |
||
| 71 | OAuth\HttpClient $httpClient, |
||
| 72 | Configuration $config, |
||
| 73 | SessionStorage $session, |
||
| 74 | Nette\Http\IRequest $httpRequest |
||
| 75 | ){ |
||
| 76 | parent::__construct($consumer, $httpClient, $config); |
||
| 77 | |||
| 78 | $this->session = $session; |
||
| 79 | $this->httpRequest = $httpRequest; |
||
| 80 | |||
| 81 | $this->consumer->setCallbackUrl($this->getCurrentUrl()); |
||
| 82 | } |
||
| 83 | |||
| 84 | /** |
||
| 85 | * @return SessionStorage |
||
| 86 | */ |
||
| 87 | public function getSession() |
||
| 91 | |||
| 92 | /** |
||
| 93 | * @return Http\UrlScript |
||
| 94 | */ |
||
| 95 | public function getCurrentUrl() |
||
| 99 | |||
| 100 | /** |
||
| 101 | * Sets the access token for api calls. Use this if you get |
||
| 102 | * your access token by other means and just want the SDK |
||
| 103 | * to use it. |
||
| 104 | * |
||
| 105 | * @param array|string $token an access token. |
||
| 106 | * |
||
| 107 | * @return $this |
||
| 108 | * |
||
| 109 | * @throws Exceptions\InvalidArgumentException |
||
| 110 | */ |
||
| 111 | public function setAccessToken($token) |
||
| 112 | { |
||
| 113 | if (!is_array($token)) { |
||
| 114 | try { |
||
| 115 | $token = Utils\Json::decode($token, Utils\Json::FORCE_ARRAY); |
||
| 116 | |||
| 117 | } catch (Utils\JsonException $ex) { |
||
| 118 | throw new Exceptions\InvalidArgumentException($ex->getMessage(), 0, $ex); |
||
| 119 | } |
||
| 120 | } |
||
| 121 | |||
| 122 | if (!isset($token['access_token']) || !isset($token['access_token_secret'])) { |
||
| 123 | throw new Exceptions\InvalidArgumentException("It's required that the token has 'access_token' and 'access_token_secret' field."); |
||
| 124 | } |
||
| 125 | |||
| 126 | $this->accessToken = new OAuth\Token($token['access_token'], $token['access_token_secret']); |
||
| 127 | |||
| 128 | return $this; |
||
| 129 | } |
||
| 130 | |||
| 131 | /** |
||
| 132 | * Determines the access token that should be used for API calls. |
||
| 133 | * The first time this is called, $this->accessToken is set equal |
||
| 134 | * to either a valid user access token, or it's set to the application |
||
| 135 | * access token if a valid user access token wasn't available. Subsequent |
||
| 136 | * calls return whatever the first call returned. |
||
| 137 | * |
||
| 138 | * @return OAuth\Token The access token |
||
| 139 | */ |
||
| 140 | public function getAccessToken() |
||
| 141 | { |
||
| 142 | if ($this->accessToken === NULL && ($accessToken = $this->getUserAccessToken())) { |
||
| 143 | $this->setAccessToken($accessToken); |
||
| 144 | } |
||
| 145 | |||
| 146 | return $this->accessToken; |
||
| 147 | } |
||
| 148 | |||
| 149 | /** |
||
| 150 | * Determines and returns the user access token, first using |
||
| 151 | * the signed request if present, and then falling back on |
||
| 152 | * the authorization code if present. The intent is to |
||
| 153 | * return a valid user access token, or false if one is determined |
||
| 154 | * to not be available. |
||
| 155 | * |
||
| 156 | * @return string A valid user access token, or false if one could not be determined. |
||
| 157 | */ |
||
| 158 | protected function getUserAccessToken() |
||
| 159 | { |
||
| 160 | if (($verifier = $this->getVerifier()) && ($token = $this->getToken())) { |
||
| 161 | if ($this->obtainAccessToken($verifier, $token)) { |
||
| 162 | return [ |
||
| 163 | 'access_token' => $this->session->access_token, |
||
| 164 | 'access_token_secret' => $this->session->access_token_secret |
||
| 165 | ]; |
||
| 166 | } |
||
| 167 | |||
| 168 | // verifier was bogus, so everything based on it should be invalidated. |
||
| 169 | $this->session->clearAll(); |
||
| 170 | |||
| 171 | return FALSE; |
||
| 172 | } |
||
| 173 | |||
| 174 | // as a fallback, just return whatever is in the persistent |
||
| 175 | // store, knowing nothing explicit (signed request, authorization |
||
| 176 | // code, etc.) was present to shadow it (or we saw a code in $_REQUEST, |
||
| 177 | // but it's the same as what's in the persistent store) |
||
| 178 | return [ |
||
| 179 | 'access_token' => $this->session->access_token, |
||
| 180 | 'access_token_secret' => $this->session->access_token_secret |
||
| 181 | ]; |
||
| 182 | } |
||
| 183 | |||
| 184 | /** |
||
| 185 | * Get the UID of the connected user, or 0 if the Twitter user is not connected. |
||
| 186 | * |
||
| 187 | * @return string the UID if available. |
||
| 188 | */ |
||
| 189 | public function getUser() |
||
| 190 | { |
||
| 191 | if ($this->user === NULL) { |
||
| 192 | $this->user = $this->getUserFromAvailableData(); |
||
| 193 | } |
||
| 194 | |||
| 195 | return $this->user; |
||
| 196 | } |
||
| 197 | |||
| 198 | /** |
||
| 199 | * @param int|string $profileId |
||
| 200 | * |
||
| 201 | * @return Profile |
||
| 202 | */ |
||
| 203 | public function getProfile($profileId = NULL) |
||
| 207 | |||
| 208 | /** |
||
| 209 | * Retrieves the UID with the understanding that $this->accessToken has already been set and is seemingly legitimate |
||
| 210 | * It relies on Twitter's API to retrieve user information and then extract the user ID. |
||
| 211 | * |
||
| 212 | * @return integer Returns the UID of the Twitter user, or 0 if the Twitter user could not be determined |
||
| 213 | */ |
||
| 214 | protected function getUserFromAccessToken() |
||
| 231 | |||
| 232 | /** |
||
| 233 | * Determines the connected user by first examining any signed |
||
| 234 | * requests, then considering an authorization code, and then |
||
| 235 | * falling back to any persistent store storing the user. |
||
| 236 | * |
||
| 237 | * @return integer The id of the connected Twitter user, or 0 if no such user exists |
||
| 238 | */ |
||
| 239 | protected function getUserFromAvailableData() |
||
| 256 | |||
| 257 | /** |
||
| 258 | * Get a request token from Twitter |
||
| 259 | * |
||
| 260 | * @param string|null $callback |
||
| 261 | * |
||
| 262 | * @return bool |
||
| 263 | */ |
||
| 264 | public function obtainRequestToken($callback = NULL) |
||
| 295 | |||
| 296 | /** |
||
| 297 | * Retrieves an access token and access token secret for the given authorization verifier and token |
||
| 298 | * (previously generated from www.twitter.com on behalf of a specific user). |
||
| 299 | * The authorization verifier and token is sent to www.twitter.com/services/oauth |
||
| 300 | * and a legitimate access token is generated provided the access token |
||
| 301 | * and the user for which it was generated all match, and the user is |
||
| 302 | * either logged in to Twitter or has granted an offline access permission |
||
| 303 | * |
||
| 304 | * @param string $verifier |
||
| 305 | * @param string $token |
||
| 306 | * |
||
| 307 | * @return bool |
||
| 308 | */ |
||
| 309 | protected function obtainAccessToken($verifier, $token) |
||
| 346 | |||
| 347 | /** |
||
| 348 | * Get the authorization verifier from the query parameters, if it exists, |
||
| 349 | * and otherwise return false to signal no authorization verifier was |
||
| 350 | * discoverable. |
||
| 351 | * |
||
| 352 | * @return mixed The authorization verifier, or false if the authorization verifier could not be determined. |
||
| 353 | */ |
||
| 354 | protected function getVerifier() |
||
| 362 | |||
| 363 | /** |
||
| 364 | * Get the authorization verifier from the query parameters, if it exists, |
||
| 365 | * and otherwise return false to signal no authorization verifier was |
||
| 366 | * discoverable. |
||
| 367 | * |
||
| 368 | * @return mixed The authorization verifier, or false if the authorization verifier could not be determined. |
||
| 369 | */ |
||
| 370 | protected function getToken() |
||
| 378 | |||
| 379 | /** |
||
| 380 | * Destroy the current session |
||
| 381 | * |
||
| 382 | * @return $this |
||
| 383 | */ |
||
| 384 | public function destroySession() |
||
| 392 | |||
| 393 | /** |
||
| 394 | * @param string $key |
||
| 395 | * @param mixed $default |
||
| 396 | * |
||
| 397 | * @return mixed|null |
||
| 398 | */ |
||
| 399 | protected function getRequest($key, $default = NULL) |
||
| 411 | } |
||
| 412 |