Complex classes like REST 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 REST, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
14 | class REST implements ServiceInterface |
||
15 | { |
||
16 | /** |
||
17 | * REST adapter |
||
18 | * @var Client |
||
19 | */ |
||
20 | protected $adapter; |
||
21 | |||
22 | /** |
||
23 | * Application token |
||
24 | * @var string |
||
25 | */ |
||
26 | private $token = null; |
||
27 | |||
28 | /** |
||
29 | * Initiate this REST service with the application token and a instance |
||
30 | * of the REST adapter (Guzzle). |
||
31 | * |
||
32 | * @param string $token |
||
33 | * @param Client $adapter |
||
34 | */ |
||
35 | 45 | public function __construct($token, Client $adapter) |
|
40 | |||
41 | 44 | private function getToken() |
|
45 | |||
46 | /** |
||
47 | * Get a request result. |
||
48 | * Returns an array with a response body or and error code => reason. |
||
49 | * @param \GuzzleHttp\Psr7\Response $response |
||
50 | * @return array|mixed |
||
51 | */ |
||
52 | 44 | private function getResult($response) |
|
53 | { |
||
54 | 44 | $status = $response->getStatusCode(); |
|
55 | 44 | if ($status == 200) { |
|
56 | 44 | return json_decode($response->getBody(), JSON_PRETTY_PRINT); |
|
57 | } else { |
||
58 | return [$status => $response->getReasonPhrase()]; |
||
59 | } |
||
60 | } |
||
61 | |||
62 | /** |
||
63 | * Get an API request response and handle possible exceptions. |
||
64 | * |
||
65 | * @param string $method |
||
66 | * @param string $path |
||
67 | * @param array $parameters |
||
68 | * |
||
69 | * @return array|mixed|string |
||
70 | */ |
||
71 | 44 | private function getResponse($method, $path, $parameters) |
|
72 | { |
||
73 | try { |
||
74 | 44 | $response = $this->adapter->request($method, $path, $parameters); |
|
75 | 44 | return $this->getResult($response); |
|
|
|||
76 | } |
||
77 | catch (\Exception $e) { |
||
78 | return $e->getMessage(); |
||
79 | } |
||
80 | } |
||
81 | |||
82 | 2 | public function getAthlete($id = null) |
|
91 | |||
92 | 1 | public function getAthleteStats($id) |
|
93 | { |
||
94 | 1 | $path = 'athletes/' . $id . '/stats'; |
|
95 | 1 | $parameters['query'] = ['access_token' => $this->getToken()]; |
|
96 | 1 | return $this->getResponse('GET', $path, $parameters); |
|
97 | } |
||
98 | |||
99 | 1 | public function getAthleteRoutes($id, $type = null, $after = null, $page = null, $per_page = null) |
|
100 | { |
||
101 | 1 | $path = 'athletes/' . $id . '/routes'; |
|
102 | 1 | $parameters['query'] = [ |
|
103 | 1 | 'type' => $type, |
|
104 | 1 | 'after' => $after, |
|
105 | 1 | 'page' => $page, |
|
106 | 1 | 'per_page' => $per_page, |
|
107 | 1 | 'access_token' => $this->getToken(), |
|
108 | ]; |
||
109 | 1 | return $this->getResponse('GET', $path, $parameters); |
|
110 | } |
||
111 | |||
112 | 1 | public function getAthleteClubs() |
|
118 | |||
119 | 1 | public function getAthleteActivities($before = null, $after = null, $page = null, $per_page = null) |
|
120 | { |
||
121 | 1 | $path = 'athlete/activities'; |
|
122 | 1 | $parameters['query'] = [ |
|
123 | 1 | 'before' => $before, |
|
124 | 1 | 'after' => $after, |
|
125 | 1 | 'page' => $page, |
|
126 | 1 | 'per_page' => $per_page, |
|
127 | 1 | 'access_token' => $this->getToken(), |
|
128 | ]; |
||
129 | 1 | return $this->getResponse('GET', $path, $parameters); |
|
130 | } |
||
131 | |||
132 | 2 | public function getAthleteFriends($id = null, $page = null, $per_page = null) |
|
133 | { |
||
134 | 2 | $path = 'athlete/friends'; |
|
135 | 2 | if (isset($id) && $id !== null) { |
|
136 | 1 | $path = 'athletes/' . $id . '/friends'; |
|
137 | 1 | } |
|
138 | 2 | $parameters['query'] = [ |
|
139 | 2 | 'page' => $page, |
|
140 | 2 | 'per_page' => $per_page, |
|
141 | 2 | 'access_token' => $this->getToken(), |
|
142 | ]; |
||
143 | 2 | return $this->getResponse('GET', $path, $parameters); |
|
144 | } |
||
145 | |||
146 | 2 | public function getAthleteFollowers($id = null, $page = null, $per_page = null) |
|
147 | { |
||
148 | 2 | $path = 'athlete/followers'; |
|
149 | 2 | if (isset($id) && $id !== null) { |
|
150 | 1 | $path = 'athletes/' . $id . '/followers'; |
|
151 | 1 | } |
|
152 | 2 | $parameters['query'] = [ |
|
153 | 2 | 'page' => $page, |
|
154 | 2 | 'per_page' => $per_page, |
|
155 | 2 | 'access_token' => $this->getToken(), |
|
156 | ]; |
||
157 | 2 | return $this->getResponse('GET', $path, $parameters); |
|
158 | } |
||
159 | |||
160 | 1 | public function getAthleteBothFollowing($id, $page = null, $per_page = null) |
|
161 | { |
||
162 | 1 | $path = 'athletes/' . $id . '/both-following'; |
|
163 | 1 | $parameters['query'] = [ |
|
164 | 1 | 'page' => $page, |
|
165 | 1 | 'per_page' => $per_page, |
|
166 | 1 | 'access_token' => $this->getToken(), |
|
167 | ]; |
||
168 | 1 | return $this->getResponse('GET', $path, $parameters); |
|
169 | } |
||
170 | |||
171 | 1 | public function getAthleteKom($id, $page = null, $per_page = null) |
|
172 | { |
||
173 | 1 | $path = 'athletes/' . $id . '/koms'; |
|
174 | 1 | $parameters['query'] = [ |
|
175 | 1 | 'page' => $page, |
|
176 | 1 | 'per_page' => $per_page, |
|
177 | 1 | 'access_token' => $this->getToken(), |
|
178 | ]; |
||
179 | 1 | return $this->getResponse('GET', $path, $parameters); |
|
180 | } |
||
181 | |||
182 | 1 | public function getAthleteZones() |
|
183 | { |
||
184 | 1 | $path = 'athlete/zones'; |
|
185 | 1 | $parameters['query'] = ['access_token' => $this->getToken()]; |
|
186 | 1 | return $this->getResponse('GET', $path, $parameters); |
|
187 | } |
||
188 | |||
189 | 2 | public function getAthleteStarredSegments($id = null, $page = null, $per_page = null) |
|
190 | { |
||
191 | 2 | $path = 'segments/starred'; |
|
192 | 2 | if (isset($id) && $id !== null) { |
|
193 | 1 | $path = 'athletes/' . $id . '/segments/starred'; |
|
194 | // ...wrong in Strava documentation |
||
195 | 1 | } |
|
196 | 2 | $parameters['query'] = [ |
|
197 | 2 | 'page' => $page, |
|
198 | 2 | 'per_page' => $per_page, |
|
199 | 2 | 'access_token' => $this->getToken(), |
|
200 | ]; |
||
201 | 2 | return $this->getResponse('GET', $path, $parameters); |
|
202 | } |
||
203 | |||
204 | 1 | public function updateAthlete($city, $state, $country, $sex, $weight) |
|
205 | { |
||
206 | 1 | $path = 'athlete'; |
|
207 | 1 | $parameters['query'] = [ |
|
208 | 1 | 'city' => $city, |
|
209 | 1 | 'state' => $state, |
|
210 | 1 | 'country' => $country, |
|
211 | 1 | 'sex' => $sex, |
|
212 | 1 | 'weight' => $weight, |
|
213 | 1 | 'access_token' => $this->getToken(), |
|
214 | ]; |
||
215 | 1 | return $this->getResponse('PUT', $path, $parameters); |
|
216 | } |
||
217 | |||
218 | public function getActivityFollowing($before = null, $page = null, $per_page = null) |
||
219 | { |
||
220 | $path = 'activities/following'; |
||
221 | $parameters['query'] = [ |
||
222 | 'before' => $before, |
||
223 | 'page' => $page, |
||
224 | 'per_page' => $per_page, |
||
225 | 'access_token' => $this->getToken(), |
||
226 | ]; |
||
227 | return $this->getResponse('GET', $path, $parameters); |
||
228 | } |
||
229 | |||
230 | 1 | public function getActivity($id, $include_all_efforts = null) |
|
231 | { |
||
232 | 1 | $path = 'activities/' . $id; |
|
233 | 1 | $parameters['query'] = [ |
|
234 | 1 | 'include_all_efforts' => $include_all_efforts, |
|
235 | 1 | 'access_token' => $this->getToken(), |
|
236 | ]; |
||
237 | 1 | return $this->getResponse('GET', $path, $parameters); |
|
238 | } |
||
239 | |||
240 | 1 | public function getActivityComments($id, $markdown = null, $page = null, $per_page = null) |
|
241 | { |
||
242 | 1 | $path = 'activities/' . $id . '/comments'; |
|
243 | 1 | $parameters['query'] = [ |
|
244 | 1 | 'markdown' => $markdown, |
|
245 | 1 | 'page' => $page, |
|
246 | 1 | 'per_page' => $per_page, |
|
247 | 1 | 'access_token' => $this->getToken(), |
|
248 | ]; |
||
249 | 1 | return $this->getResponse('GET', $path, $parameters); |
|
250 | } |
||
251 | |||
252 | 1 | public function getActivityKudos($id, $page = null, $per_page = null) |
|
253 | { |
||
254 | 1 | $path = 'activities/' . $id . '/kudos'; |
|
255 | 1 | $parameters['query'] = [ |
|
256 | 1 | 'page' => $page, |
|
257 | 1 | 'per_page' => $per_page, |
|
258 | 1 | 'access_token' => $this->getToken(), |
|
259 | ]; |
||
260 | 1 | return $this->getResponse('GET', $path, $parameters); |
|
261 | } |
||
262 | |||
263 | 1 | public function getActivityPhotos($id, $size = 2048, $photo_sources = 'true') |
|
264 | { |
||
265 | 1 | $path = 'activities/' . $id . '/photos'; |
|
266 | 1 | $parameters['query'] = [ |
|
267 | 1 | 'size' => $size, |
|
268 | 1 | 'photo_sources' => $photo_sources, |
|
269 | 1 | 'access_token' => $this->getToken(), |
|
270 | ]; |
||
271 | 1 | return $this->getResponse('GET', $path, $parameters); |
|
272 | } |
||
273 | |||
274 | 1 | public function getActivityZones($id) |
|
280 | |||
281 | 1 | public function getActivityLaps($id) |
|
282 | { |
||
283 | 1 | $path = 'activities/' . $id . '/laps'; |
|
284 | 1 | $parameters['query'] = ['access_token' => $this->getToken()]; |
|
285 | 1 | return $this->getResponse('GET', $path, $parameters); |
|
286 | } |
||
287 | |||
288 | 1 | public function getActivityUploadStatus($id) |
|
289 | { |
||
290 | 1 | $path = 'uploads/' . $id; |
|
291 | 1 | $parameters['query'] = ['access_token' => $this->getToken()]; |
|
292 | 1 | return $this->getResponse('GET', $path, $parameters); |
|
293 | } |
||
294 | |||
295 | 1 | public function createActivity($name, $type, $start_date_local, $elapsed_time, $description = null, $distance = null, $private = null, $trainer = null) |
|
296 | { |
||
297 | 1 | $path = 'activities'; |
|
298 | 1 | $parameters['query'] = [ |
|
299 | 1 | 'name' => $name, |
|
300 | 1 | 'type' => $type, |
|
301 | 1 | 'start_date_local' => $start_date_local, |
|
302 | 1 | 'elapsed_time' => $elapsed_time, |
|
303 | 1 | 'description' => $description, |
|
304 | 1 | 'distance' => $distance, |
|
305 | 1 | 'private' => $private, |
|
306 | 1 | 'trainer' => $trainer, |
|
307 | 1 | 'access_token' => $this->getToken(), |
|
308 | ]; |
||
309 | 1 | return $this->getResponse('POST', $path, $parameters); |
|
310 | } |
||
311 | |||
312 | 1 | public function uploadActivity($file, $activity_type = null, $name = null, $description = null, $private = null, $trainer = null, $commute = null, $data_type = null, $external_id = null) |
|
313 | { |
||
314 | 1 | $path = 'uploads'; |
|
315 | 1 | $parameters['query'] = [ |
|
316 | 1 | 'activity_type' => $activity_type, |
|
317 | 1 | 'name' => $name, |
|
318 | 1 | 'description' => $description, |
|
319 | 1 | 'private' => $private, |
|
320 | 1 | 'trainer' => $trainer, |
|
321 | 1 | 'commute' => $commute, |
|
322 | 1 | 'data_type' => $data_type, |
|
323 | 1 | 'external_id' => $external_id, |
|
324 | 1 | 'file' => curl_file_create($file), |
|
325 | 1 | 'file_hack' => '@' . ltrim($file, '@'), |
|
326 | 1 | 'access_token' => $this->getToken(), |
|
327 | ]; |
||
328 | 1 | return $this->getResponse('POST', $path, $parameters); |
|
329 | } |
||
330 | |||
331 | 1 | public function updateActivity($id, $name = null, $type = null, $private = false, $commute = false, $trainer = false, $gear_id = null, $description = null) |
|
332 | { |
||
333 | 1 | $path = 'activities/' . $id; |
|
334 | 1 | $parameters['query'] = [ |
|
335 | 1 | 'name' => $name, |
|
336 | 1 | 'type' => $type, |
|
337 | 1 | 'private' => $private, |
|
338 | 1 | 'commute' => $commute, |
|
339 | 1 | 'trainer' => $trainer, |
|
340 | 1 | 'gear_id' => $gear_id, |
|
341 | 1 | 'description' => $description, |
|
342 | 1 | 'access_token' => $this->getToken(), |
|
343 | ]; |
||
344 | 1 | return $this->getResponse('PUT', $path, $parameters); |
|
345 | } |
||
346 | |||
347 | 1 | public function deleteActivity($id) |
|
353 | |||
354 | 1 | public function getGear($id) |
|
355 | { |
||
356 | 1 | $path = 'gear/' . $id; |
|
357 | 1 | $parameters['query'] = ['access_token' => $this->getToken()]; |
|
358 | 1 | return $this->getResponse('GET', $path, $parameters); |
|
359 | } |
||
360 | |||
361 | 1 | public function getClub($id) |
|
362 | { |
||
363 | 1 | $path = 'clubs/' . $id; |
|
364 | 1 | $parameters['query'] = ['access_token' => $this->getToken()]; |
|
365 | 1 | return $this->getResponse('GET', $path, $parameters); |
|
366 | } |
||
367 | |||
368 | 1 | public function getClubMembers($id, $page = null, $per_page = null) |
|
369 | { |
||
370 | 1 | $path = 'clubs/' . $id . '/members'; |
|
371 | 1 | $parameters['query'] = [ |
|
372 | 1 | 'page' => $page, |
|
373 | 1 | 'per_page' => $per_page, |
|
374 | 1 | 'access_token' => $this->getToken(), |
|
375 | ]; |
||
376 | 1 | return $this->getResponse('GET', $path, $parameters); |
|
377 | } |
||
378 | |||
379 | 1 | public function getClubActivities($id, $page = null, $per_page = null) |
|
380 | { |
||
381 | 1 | $path = 'clubs/' . $id . '/activities'; |
|
382 | 1 | $parameters['query'] = [ |
|
383 | 1 | 'page' => $page, |
|
384 | 1 | 'per_page' => $per_page, |
|
385 | 1 | 'access_token' => $this->getToken(), |
|
386 | ]; |
||
387 | 1 | return $this->getResponse('GET', $path, $parameters); |
|
388 | } |
||
389 | |||
390 | 1 | public function getClubAnnouncements($id) |
|
391 | { |
||
392 | 1 | $path = 'clubs/' . $id . '/announcements'; |
|
393 | 1 | $parameters['query'] = ['access_token' => $this->getToken()]; |
|
394 | 1 | return $this->getResponse('GET', $path, $parameters); |
|
395 | } |
||
396 | |||
397 | 1 | public function getClubGroupEvents($id) |
|
398 | { |
||
399 | 1 | $path = 'clubs/' . $id . '/group_events'; |
|
400 | 1 | $parameters['query'] = ['access_token' => $this->getToken()]; |
|
401 | 1 | return $this->getResponse('GET', $path, $parameters); |
|
402 | } |
||
403 | |||
404 | 1 | public function joinClub($id) |
|
405 | { |
||
406 | 1 | $path = 'clubs/' . $id . '/join'; |
|
407 | 1 | $parameters['query'] = ['access_token' => $this->getToken()]; |
|
408 | 1 | return $this->getResponse('POST', $path, $parameters); |
|
409 | } |
||
410 | |||
411 | 1 | public function leaveClub($id) |
|
412 | { |
||
413 | 1 | $path = 'clubs/' . $id . '/leave'; |
|
414 | 1 | $parameters['query'] = ['access_token' => $this->getToken()]; |
|
415 | 1 | return $this->getResponse('POST', $path, $parameters); |
|
416 | } |
||
417 | |||
418 | 1 | public function getRoute($id) |
|
424 | |||
425 | 1 | public function getSegment($id) |
|
426 | { |
||
427 | 1 | $path = 'segments/' . $id; |
|
428 | 1 | $parameters['query'] = ['access_token' => $this->getToken()]; |
|
429 | 1 | return $this->getResponse('GET', $path, $parameters); |
|
430 | } |
||
431 | |||
432 | 1 | public function getSegmentLeaderboard($id, $gender = null, $age_group = null, $weight_class = null, $following = null, $club_id = null, $date_range = null, $context_entries = null, $page = null, $per_page = null) |
|
433 | { |
||
434 | 1 | $path = 'segments/' . $id . '/leaderboard'; |
|
435 | 1 | $parameters['query'] = [ |
|
436 | 1 | 'gender' => $gender, |
|
437 | 1 | 'age_group' => $age_group, |
|
438 | 1 | 'weight_class' => $weight_class, |
|
439 | 1 | 'following' => $following, |
|
440 | 1 | 'club_id' => $club_id, |
|
441 | 1 | 'date_range' => $date_range, |
|
442 | 1 | 'context_entries' => $context_entries, |
|
443 | 1 | 'page' => $page, |
|
444 | 1 | 'per_page' => $per_page, |
|
445 | 1 | 'access_token' => $this->getToken(), |
|
446 | ]; |
||
447 | 1 | return $this->getResponse('GET', $path, $parameters); |
|
448 | } |
||
449 | |||
450 | 1 | public function getSegmentExplorer($bounds, $activity_type = 'riding', $min_cat = null, $max_cat = null) |
|
451 | { |
||
452 | 1 | $path = 'segments/explore'; |
|
453 | 1 | $parameters['query'] = [ |
|
454 | 1 | 'bounds' => $bounds, |
|
455 | 1 | 'activity_type' => $activity_type, |
|
456 | 1 | 'min_cat' => $min_cat, |
|
462 | |||
463 | 1 | public function getSegmentEffort($id, $athlete_id = null, $start_date_local = null, $end_date_local = null, $page = null, $per_page = null) |
|
476 | |||
477 | 1 | public function getStreamsActivity($id, $types, $resolution = null, $series_type = 'distance') |
|
487 | |||
488 | 1 | public function getStreamsEffort($id, $types, $resolution = null, $series_type = 'distance') |
|
498 | |||
499 | 1 | public function getStreamsSegment($id, $types, $resolution = null, $series_type = 'distance') |
|
509 | |||
510 | 1 | public function getStreamsRoute($id) |
|
516 | |||
517 | } |
||
518 |
This check looks for parameters that are defined as one type in their type hint or doc comment but seem to be used as a narrower type, i.e an implementation of an interface or a subclass.
Consider changing the type of the parameter or doing an instanceof check before assuming your parameter is of the expected type.