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 |
||
17 | class Client |
||
18 | { |
||
19 | public const THUMBNAIL_FORMAT_JPEG = 'jpeg'; |
||
20 | public const THUMBNAIL_FORMAT_PNG = 'png'; |
||
21 | |||
22 | public const THUMBNAIL_SIZE_XS = 'w32h32'; |
||
23 | public const THUMBNAIL_SIZE_S = 'w64h64'; |
||
24 | public const THUMBNAIL_SIZE_M = 'w128h128'; |
||
25 | public const THUMBNAIL_SIZE_L = 'w640h480'; |
||
26 | public const THUMBNAIL_SIZE_XL = 'w1024h768'; |
||
27 | |||
28 | public const MAX_CHUNK_SIZE = 1024 * 1024 * 150; |
||
29 | |||
30 | public const UPLOAD_SESSION_START = 0; |
||
31 | public const UPLOAD_SESSION_APPEND = 1; |
||
32 | |||
33 | /** |
||
34 | * @var string |
||
35 | */ |
||
36 | protected $accessToken; |
||
37 | |||
38 | /** |
||
39 | * @var string |
||
40 | */ |
||
41 | protected $appKey; |
||
42 | |||
43 | /** |
||
44 | * @var string |
||
45 | */ |
||
46 | protected $appSecret; |
||
47 | |||
48 | /** |
||
49 | * @var \GuzzleHttp\Client |
||
50 | */ |
||
51 | protected $client; |
||
52 | |||
53 | /** |
||
54 | * @var int |
||
55 | */ |
||
56 | protected $maxChunkSize; |
||
57 | |||
58 | /** |
||
59 | * @var int |
||
60 | */ |
||
61 | protected $maxUploadChunkRetries; |
||
62 | |||
63 | /** |
||
64 | * @param string|array|null $accessTokenOrAppCredentials |
||
65 | * @param GuzzleClient|null $client |
||
66 | * @param int $maxChunkSize Set max chunk size per request (determines when to switch from "one shot upload" to upload session and defines chunk size for uploads via session). |
||
67 | * @param int $maxUploadChunkRetries How many times to retry an upload session start or append after RequestException. |
||
68 | */ |
||
69 | public function __construct($accessTokenOrAppCredentials = null, GuzzleClient $client = null, int $maxChunkSize = self::MAX_CHUNK_SIZE, int $maxUploadChunkRetries = 0) |
||
83 | |||
84 | /** |
||
85 | * Copy a file or folder to a different location in the user's Dropbox. |
||
86 | * |
||
87 | * If the source path is a folder all its contents will be copied. |
||
88 | * |
||
89 | * @link https://www.dropbox.com/developers/documentation/http/documentation#files-copy_v2 |
||
90 | * |
||
91 | * @param string $fromPath |
||
92 | * @param string $toPath |
||
93 | * @return array |
||
94 | * @throws Exception |
||
95 | */ |
||
96 | public function copy(string $fromPath, string $toPath): array |
||
105 | |||
106 | /** |
||
107 | * Create a folder at a given path. |
||
108 | * |
||
109 | * @link https://www.dropbox.com/developers/documentation/http/documentation#files-create_folder |
||
110 | * |
||
111 | * @param string $path |
||
112 | * @return array |
||
113 | * @throws Exception |
||
114 | */ |
||
115 | public function createFolder(string $path): array |
||
127 | |||
128 | /** |
||
129 | * Create a shared link with custom settings. |
||
130 | * |
||
131 | * If no settings are given then the default visibility is RequestedVisibility.public. |
||
132 | * The resolved visibility, though, may depend on other aspects such as team and |
||
133 | * shared folder settings). Only for paid users. |
||
134 | * |
||
135 | * @link https://www.dropbox.com/developers/documentation/http/documentation#sharing-create_shared_link_with_settings |
||
136 | * |
||
137 | * @param string $path |
||
138 | * @param array $settings |
||
139 | * @return array |
||
140 | * @throws Exception |
||
141 | */ |
||
142 | public function createSharedLinkWithSettings(string $path, array $settings = []): array |
||
154 | |||
155 | /** |
||
156 | * Search a file or folder in the user's Dropbox. |
||
157 | * |
||
158 | * @link https://www.dropbox.com/developers/documentation/http/documentation#files-search |
||
159 | * |
||
160 | * @param string $query |
||
161 | * @param bool $includeHighlights |
||
162 | * @return array |
||
163 | * @throws Exception |
||
164 | */ |
||
165 | public function search(string $query, bool $includeHighlights = false): array |
||
174 | |||
175 | /** |
||
176 | * List shared links. |
||
177 | * |
||
178 | * For empty path returns a list of all shared links. For non-empty path |
||
179 | * returns a list of all shared links with access to the given path. |
||
180 | * |
||
181 | * If direct_only is set true, only direct links to the path will be returned, otherwise |
||
182 | * it may return link to the path itself and parent folders as described on docs. |
||
183 | * |
||
184 | * @link https://www.dropbox.com/developers/documentation/http/documentation#sharing-list_shared_links |
||
185 | * |
||
186 | * @param string|null $path |
||
187 | * @param bool $direct_only |
||
188 | * @param string|null $cursor |
||
189 | * @return array |
||
190 | * @throws Exception |
||
191 | */ |
||
192 | public function listSharedLinks(string $path = null, bool $direct_only = false, string $cursor = null): array |
||
204 | |||
205 | /** |
||
206 | * Delete the file or folder at a given path. |
||
207 | * |
||
208 | * If the path is a folder, all its contents will be deleted too. |
||
209 | * A successful response indicates that the file or folder was deleted. |
||
210 | * |
||
211 | * @link https://www.dropbox.com/developers/documentation/http/documentation#files-delete |
||
212 | * |
||
213 | * @param string $path |
||
214 | * @return array |
||
215 | * @throws Exception |
||
216 | */ |
||
217 | public function delete(string $path): array |
||
225 | |||
226 | /** |
||
227 | * Download a file from a user's Dropbox. |
||
228 | * |
||
229 | * @link https://www.dropbox.com/developers/documentation/http/documentation#files-download |
||
230 | * |
||
231 | * @param string $path |
||
232 | * @return resource |
||
233 | * @throws Exception |
||
234 | */ |
||
235 | public function download(string $path) |
||
245 | |||
246 | /** |
||
247 | * Download a folder from the user's Dropbox, as a zip file. |
||
248 | * The folder must be less than 20 GB in size and have fewer than 10,000 total files. |
||
249 | * The input cannot be a single file. Any single file must be less than 4GB in size. |
||
250 | * |
||
251 | * @param string $path |
||
252 | * |
||
253 | * @return resource |
||
254 | * |
||
255 | * @link https://www.dropbox.com/developers/documentation/http/documentation#files-download_zip |
||
256 | */ |
||
257 | public function downloadZip(string $path) |
||
267 | |||
268 | /** |
||
269 | * Returns the metadata for a file or folder. |
||
270 | * |
||
271 | * Note: Metadata for the root folder is unsupported. |
||
272 | * |
||
273 | * @link https://www.dropbox.com/developers/documentation/http/documentation#files-get_metadata |
||
274 | * |
||
275 | * @param string $path |
||
276 | * @return array |
||
277 | * @throws Exception |
||
278 | */ |
||
279 | public function getMetadata(string $path): array |
||
287 | |||
288 | /** |
||
289 | * Get a temporary link to stream content of a file. |
||
290 | * |
||
291 | * This link will expire in four hours and afterwards you will get 410 Gone. |
||
292 | * Content-Type of the link is determined automatically by the file's mime type. |
||
293 | * |
||
294 | * @link https://www.dropbox.com/developers/documentation/http/documentation#files-get_temporary_link |
||
295 | * |
||
296 | * @param string $path |
||
297 | * @return string |
||
298 | * @throws Exception |
||
299 | */ |
||
300 | public function getTemporaryLink(string $path): string |
||
310 | |||
311 | /** |
||
312 | * Get a thumbnail for an image. |
||
313 | * |
||
314 | * This method currently supports files with the following file extensions: |
||
315 | * jpg, jpeg, png, tiff, tif, gif and bmp. |
||
316 | * |
||
317 | * Photos that are larger than 20MB in size won't be converted to a thumbnail. |
||
318 | * |
||
319 | * @link https://www.dropbox.com/developers/documentation/http/documentation#files-get_thumbnail |
||
320 | * |
||
321 | * @param string $path |
||
322 | * @param string $format |
||
323 | * @param string $size |
||
324 | * @return string |
||
325 | * @throws Exception |
||
326 | */ |
||
327 | public function getThumbnail(string $path, string $format = 'jpeg', string $size = 'w64h64'): string |
||
339 | |||
340 | /** |
||
341 | * Starts returning the contents of a folder. |
||
342 | * |
||
343 | * If the result's ListFolderResult.has_more field is true, call |
||
344 | * list_folder/continue with the returned ListFolderResult.cursor to retrieve more entries. |
||
345 | * |
||
346 | * Note: auth.RateLimitError may be returned if multiple list_folder or list_folder/continue calls |
||
347 | * with same parameters are made simultaneously by same API app for same user. If your app implements |
||
348 | * retry logic, please hold off the retry until the previous request finishes. |
||
349 | * |
||
350 | * @link https://www.dropbox.com/developers/documentation/http/documentation#files-list_folder |
||
351 | * |
||
352 | * @param string $path |
||
353 | * @param bool $recursive |
||
354 | * @return array |
||
355 | * @throws Exception |
||
356 | */ |
||
357 | public function listFolder(string $path = '', bool $recursive = false): array |
||
366 | |||
367 | /** |
||
368 | * Once a cursor has been retrieved from list_folder, use this to paginate through all files and |
||
369 | * retrieve updates to the folder, following the same rules as documented for list_folder. |
||
370 | * |
||
371 | * @link https://www.dropbox.com/developers/documentation/http/documentation#files-list_folder-continue |
||
372 | * |
||
373 | * @param string $cursor |
||
374 | * @return array |
||
375 | * @throws Exception |
||
376 | */ |
||
377 | public function listFolderContinue(string $cursor = ''): array |
||
381 | |||
382 | /** |
||
383 | * Move a file or folder to a different location in the user's Dropbox. |
||
384 | * |
||
385 | * If the source path is a folder all its contents will be moved. |
||
386 | * |
||
387 | * @link https://www.dropbox.com/developers/documentation/http/documentation#files-move_v2 |
||
388 | * |
||
389 | * @param string $fromPath |
||
390 | * @param string $toPath |
||
391 | * @return array |
||
392 | * @throws Exception |
||
393 | */ |
||
394 | public function move(string $fromPath, string $toPath): array |
||
403 | |||
404 | /** |
||
405 | * The file should be uploaded in chunks if it size exceeds the 150 MB threshold |
||
406 | * or if the resource size could not be determined (eg. a popen() stream). |
||
407 | * |
||
408 | * @param string|resource $contents |
||
409 | * @return bool |
||
410 | */ |
||
411 | protected function shouldUploadChunked($contents): bool |
||
425 | |||
426 | /** |
||
427 | * Check if the contents is a pipe stream (not seekable, no size defined). |
||
428 | * |
||
429 | * @param string|resource $contents |
||
430 | * @return bool |
||
431 | */ |
||
432 | protected function isPipe($contents): bool |
||
436 | |||
437 | /** |
||
438 | * Create a new file with the contents provided in the request. |
||
439 | * |
||
440 | * Do not use this to upload a file larger than 150 MB. Instead, create an upload session with upload_session/start. |
||
441 | * |
||
442 | * @link https://www.dropbox.com/developers/documentation/http/documentation#files-upload |
||
443 | * |
||
444 | * @param string $path |
||
445 | * @param string|resource $contents |
||
446 | * @param string $mode |
||
447 | * @return array |
||
448 | * @throws Exception |
||
449 | */ |
||
450 | public function upload(string $path, $contents, $mode = 'add'): array |
||
469 | |||
470 | /** |
||
471 | * Upload file split in chunks. This allows uploading large files, since |
||
472 | * Dropbox API v2 limits the content size to 150MB. |
||
473 | * |
||
474 | * The chunk size will affect directly the memory usage, so be careful. |
||
475 | * Large chunks tends to speed up the upload, while smaller optimizes memory usage. |
||
476 | * |
||
477 | * @param string $path |
||
478 | * @param string|resource $contents |
||
479 | * @param string $mode |
||
480 | * @param int|null $chunkSize |
||
481 | * @return array |
||
482 | * @throws Exception |
||
483 | */ |
||
484 | public function uploadChunked(string $path, $contents, $mode = 'add', $chunkSize = null): array |
||
500 | |||
501 | /** |
||
502 | * @param int $type |
||
503 | * @param Psr7\Stream $stream |
||
504 | * @param int $chunkSize |
||
505 | * @param UploadSessionCursor|null $cursor |
||
506 | * @return UploadSessionCursor |
||
507 | * @throws Exception |
||
508 | */ |
||
509 | protected function uploadChunk($type, &$stream, $chunkSize, $cursor = null): UploadSessionCursor |
||
540 | |||
541 | /** |
||
542 | * Upload sessions allow you to upload a single file in one or more requests, |
||
543 | * for example where the size of the file is greater than 150 MB. |
||
544 | * This call starts a new upload session with the given data. |
||
545 | * |
||
546 | * @link https://www.dropbox.com/developers/documentation/http/documentation#files-upload_session-start |
||
547 | * |
||
548 | * @param string|StreamInterface $contents |
||
549 | * @param bool $close |
||
550 | * @return UploadSessionCursor |
||
551 | * @throws Exception |
||
552 | */ |
||
553 | public function uploadSessionStart($contents, bool $close = false): UploadSessionCursor |
||
564 | |||
565 | /** |
||
566 | * Append more data to an upload session. |
||
567 | * When the parameter close is set, this call will close the session. |
||
568 | * A single request should not upload more than 150 MB. |
||
569 | * |
||
570 | * @link https://www.dropbox.com/developers/documentation/http/documentation#files-upload_session-append_v2 |
||
571 | * |
||
572 | * @param string|StreamInterface $contents |
||
573 | * @param UploadSessionCursor $cursor |
||
574 | * @param bool $close |
||
575 | * @return UploadSessionCursor |
||
576 | * @throws Exception |
||
577 | */ |
||
578 | public function uploadSessionAppend($contents, UploadSessionCursor $cursor, bool $close = false): UploadSessionCursor |
||
589 | |||
590 | /** |
||
591 | * Finish an upload session and save the uploaded data to the given file path. |
||
592 | * A single request should not upload more than 150 MB. |
||
593 | * |
||
594 | * @link https://www.dropbox.com/developers/documentation/http/documentation#files-upload_session-finish |
||
595 | * |
||
596 | * @param string|StreamInterface $contents |
||
597 | * @param UploadSessionCursor $cursor |
||
598 | * @param string $path |
||
599 | * @param string|array $mode |
||
600 | * @param bool $autorename |
||
601 | * @param bool $mute |
||
602 | * @return array |
||
603 | * @throws Exception |
||
604 | */ |
||
605 | public function uploadSessionFinish($contents, UploadSessionCursor $cursor, string $path, $mode = 'add', $autorename = false, $mute = false): array |
||
622 | |||
623 | /** |
||
624 | * Get Account Info for current authenticated user. |
||
625 | * |
||
626 | * @link https://www.dropbox.com/developers/documentation/http/documentation#users-get_current_account |
||
627 | * |
||
628 | * @return array |
||
629 | * @throws Exception |
||
630 | */ |
||
631 | public function getAccountInfo(): array |
||
635 | |||
636 | /** |
||
637 | * Revoke current access token. |
||
638 | * |
||
639 | * @link https://www.dropbox.com/developers/documentation/http/documentation#auth-token-revoke |
||
640 | * |
||
641 | * @throws Exception |
||
642 | */ |
||
643 | public function revokeToken(): void |
||
647 | |||
648 | /** |
||
649 | * @param string $path |
||
650 | * @return string |
||
651 | */ |
||
652 | protected function normalizePath(string $path): string |
||
662 | |||
663 | /** |
||
664 | * @param string $subdomain |
||
665 | * @param string $endpoint |
||
666 | * @return string |
||
667 | */ |
||
668 | protected function getEndpointUrl(string $subdomain, string $endpoint): string |
||
676 | |||
677 | /** |
||
678 | * @param string $endpoint |
||
679 | * @param array $arguments |
||
680 | * @param string $body |
||
681 | * @return ResponseInterface |
||
682 | * @throws Exception |
||
683 | */ |
||
684 | public function contentEndpointRequest(string $endpoint, array $arguments, $body = ''): ResponseInterface |
||
703 | |||
704 | /** |
||
705 | * @param string $endpoint |
||
706 | * @param array|null $parameters |
||
707 | * @return array |
||
708 | * @throws Exception |
||
709 | */ |
||
710 | public function rpcEndpointRequest(string $endpoint, array $parameters = null): array |
||
728 | |||
729 | /** |
||
730 | * @param ClientException $exception |
||
731 | * @return Exception |
||
732 | */ |
||
733 | protected function determineException(ClientException $exception): Exception |
||
741 | |||
742 | /** |
||
743 | * @param $contents |
||
744 | * @return PumpStream|StreamInterface |
||
745 | */ |
||
746 | protected function getStream($contents) |
||
762 | |||
763 | /** |
||
764 | * Get the access token. |
||
765 | * |
||
766 | * @return string |
||
767 | */ |
||
768 | public function getAccessToken(): string |
||
772 | |||
773 | /** |
||
774 | * Set the access token. |
||
775 | * |
||
776 | * @param string $accessToken |
||
777 | * @return Client |
||
778 | */ |
||
779 | public function setAccessToken(string $accessToken): self |
||
785 | |||
786 | /** |
||
787 | * Get the HTTP headers. |
||
788 | * |
||
789 | * @param array $headers |
||
790 | * @return array |
||
791 | */ |
||
792 | protected function getHeaders(array $headers = []): array |
||
800 | |||
801 | /** |
||
802 | * @return array |
||
803 | */ |
||
804 | protected function getHeadersForBearerToken() |
||
810 | |||
811 | /** |
||
812 | * @return array |
||
813 | */ |
||
814 | protected function getHeadersForCredentials() |
||
820 | } |
||
821 |
This check looks at variables that have been passed in as parameters and are passed out again to other methods.
If the outgoing method call has stricter type requirements than the method itself, an issue is raised.
An additional type check may prevent trouble.