Complex classes like RestfulService 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 RestfulService, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
10 | class RestfulService extends ViewableData implements Flushable { |
||
11 | |||
12 | protected $baseURL; |
||
13 | protected $queryString; |
||
14 | protected $errorTag; |
||
15 | protected $checkErrors; |
||
16 | protected $cache_expire; |
||
17 | protected $authUsername, $authPassword; |
||
|
|||
18 | protected $customHeaders = array(); |
||
19 | protected $proxy; |
||
20 | |||
21 | /** |
||
22 | * @config |
||
23 | * @var array |
||
24 | */ |
||
25 | private static $default_proxy; |
||
26 | |||
27 | /** |
||
28 | * @config |
||
29 | * @var array |
||
30 | */ |
||
31 | private static $default_curl_options = array(); |
||
32 | |||
33 | /** |
||
34 | * @config |
||
35 | * @var bool Flushes caches if set to true. This is set by {@link flush()} |
||
36 | */ |
||
37 | private static $flush = false; |
||
38 | |||
39 | /** |
||
40 | * Triggered early in the request when someone requests a flush. |
||
41 | */ |
||
42 | public static function flush() { |
||
45 | |||
46 | /** |
||
47 | * set a curl option that will be applied to all requests as default |
||
48 | * {@see http://php.net/manual/en/function.curl-setopt.php#refsect1-function.curl-setopt-parameters} |
||
49 | * |
||
50 | * @deprecated 4.0 Use the "RestfulService.default_curl_options" config setting instead |
||
51 | * @param int $option The cURL opt Constant |
||
52 | * @param mixed $value The cURL opt value |
||
53 | */ |
||
54 | public static function set_default_curl_option($option, $value) { |
||
58 | |||
59 | /** |
||
60 | * set many defauly curl options at once |
||
61 | * |
||
62 | * @deprecated 4.0 Use the "RestfulService.default_curl_options" config setting instead |
||
63 | */ |
||
64 | public static function set_default_curl_options($optionArray) { |
||
68 | |||
69 | /** |
||
70 | * Sets default proxy settings for outbound RestfulService connections |
||
71 | * |
||
72 | * @param string $proxy The URL of the proxy to use. |
||
73 | * @param int $port Proxy port |
||
74 | * @param string $user The proxy auth user name |
||
75 | * @param string $password The proxy auth password |
||
76 | * @param boolean $socks Set true to use socks5 proxy instead of http |
||
77 | * @deprecated 4.0 Use the "RestfulService.default_curl_options" config setting instead, |
||
78 | * with direct reference to the CURL_* options |
||
79 | */ |
||
80 | public static function set_default_proxy($proxy, $port = 80, $user = "", $password = "", $socks = false) { |
||
93 | |||
94 | /** |
||
95 | * Creates a new restful service. |
||
96 | * @param string $base Base URL of the web service eg: api.example.com |
||
97 | * @param int $expiry Set the cache expiry interva. Defaults to 1 hour (3600 seconds) |
||
98 | */ |
||
99 | public function __construct($base, $expiry=3600){ |
||
105 | |||
106 | /** |
||
107 | * Sets the Query string parameters to send a request. |
||
108 | * @param array $params An array passed with necessary parameters. |
||
109 | */ |
||
110 | public function setQueryString($params=NULL){ |
||
113 | |||
114 | /** |
||
115 | * Set proxy settings for this RestfulService instance |
||
116 | * |
||
117 | * @param string $proxy The URL of the proxy to use. |
||
118 | * @param int $port Proxy port |
||
119 | * @param string $user The proxy auth user name |
||
120 | * @param string $password The proxy auth password |
||
121 | * @param boolean $socks Set true to use socks5 proxy instead of http |
||
122 | */ |
||
123 | public function setProxy($proxy, $port = 80, $user = "", $password = "", $socks = false) { |
||
131 | |||
132 | /** |
||
133 | * Set basic authentication |
||
134 | */ |
||
135 | public function basicAuth($username, $password) { |
||
139 | |||
140 | /** |
||
141 | * Set a custom HTTP header |
||
142 | */ |
||
143 | public function httpHeader($header) { |
||
146 | |||
147 | /** |
||
148 | * @deprecated since version 4.0 |
||
149 | */ |
||
150 | protected function constructURL(){ |
||
154 | |||
155 | /** |
||
156 | * Makes a request to the RESTful server, and return a {@link RestfulService_Response} object for parsing of the |
||
157 | * result. |
||
158 | * |
||
159 | * @todo Better POST, PUT, DELETE, and HEAD support |
||
160 | * @todo Caching of requests - probably only GET and HEAD requestst |
||
161 | * @todo JSON support in RestfulService_Response |
||
162 | * @todo Pass the response headers to RestfulService_Response |
||
163 | * |
||
164 | * This is a replacement of {@link connect()}. |
||
165 | * |
||
166 | * @return RestfulService_Response - If curl request produces error, the returned response's status code will |
||
167 | * be 500 |
||
168 | */ |
||
169 | public function request($subURL = '', $method = "GET", $data = null, $headers = null, $curlOptions = array()) { |
||
220 | |||
221 | /** |
||
222 | * Actually performs a remote service request using curl. This is used by |
||
223 | * {@link RestfulService::request()}. |
||
224 | * |
||
225 | * @param string $url |
||
226 | * @param string $method |
||
227 | * @param array $data |
||
228 | * @param array $headers |
||
229 | * @param array $curlOptions |
||
230 | * @return RestfulService_Response |
||
231 | */ |
||
232 | public function curlRequest($url, $method, $data = null, $headers = null, $curlOptions = array()) { |
||
294 | |||
295 | /** |
||
296 | * A function to return the auth string. This helps consistency through the |
||
297 | * class but also allows tests to pull it out when generating the expected |
||
298 | * cache keys |
||
299 | * |
||
300 | * @see {self::getCachePath()} |
||
301 | * @see {RestfulServiceTest::createFakeCachedResponse()} |
||
302 | * |
||
303 | * @return string The auth string to be base64 encoded |
||
304 | */ |
||
305 | protected function getBasicAuthString() { |
||
308 | |||
309 | /** |
||
310 | * Generate a cache key based on any cache data sent. The cache data can be |
||
311 | * any type |
||
312 | * |
||
313 | * @param mixed $cacheData The cache seed for generating the key |
||
314 | * @param string the md5 encoded cache seed. |
||
315 | */ |
||
316 | protected function generateCacheKey($cacheData) { |
||
319 | |||
320 | /** |
||
321 | * Generate the cache path |
||
322 | * |
||
323 | * This is mainly so that the cache path can be generated in a consistent |
||
324 | * way in tests without having to hard code the cachekey generate function |
||
325 | * in tests |
||
326 | * |
||
327 | * @param mixed $cacheData The cache seed {@see self::generateCacheKey} |
||
328 | * |
||
329 | * @return string The path to the cache file |
||
330 | */ |
||
331 | protected function getCachePath($cacheData) { |
||
334 | |||
335 | /** |
||
336 | * Extracts the response body and headers from a full curl response |
||
337 | * |
||
338 | * @param curl_handle $ch The curl handle for the request |
||
339 | * @param string $rawResponse The raw response text |
||
340 | * |
||
341 | * @return RestfulService_Response The response object |
||
342 | */ |
||
343 | protected function extractResponse($ch, $rawHeaders, $rawBody) { |
||
357 | |||
358 | /** |
||
359 | * Takes raw headers and parses them to turn them to an associative array |
||
360 | * |
||
361 | * Any header that we see more than once is turned into an array. |
||
362 | * |
||
363 | * This is meant to mimic http_parse_headers {@link http://php.net/manual/en/function.http-parse-headers.php} |
||
364 | * thanks to comment #77241 on that page for foundation of this |
||
365 | * |
||
366 | * @param string $rawHeaders The raw header string |
||
367 | * @return array The assosiative array of headers |
||
368 | */ |
||
369 | protected function parseRawHeaders($rawHeaders) { |
||
393 | |||
394 | |||
395 | /** |
||
396 | * Returns a full request url |
||
397 | * @param string |
||
398 | */ |
||
399 | public function getAbsoluteRequestURL($subURL = '') { |
||
404 | |||
405 | /** |
||
406 | * Gets attributes as an array, of a particular type of element. |
||
407 | * Example : <photo id="2636" owner="123" secret="ab128" server="2"> |
||
408 | * returns id, owner,secret and sever attribute values of all such photo elements. |
||
409 | * @param string $xml The source xml to parse, this could be the original response received. |
||
410 | * @param string $collection The name of parent node which wraps the elements, if available |
||
411 | * @param string $element The element we need to extract the attributes. |
||
412 | */ |
||
413 | |||
414 | public function getAttributes($xml, $collection=NULL, $element=NULL){ |
||
435 | |||
436 | /** |
||
437 | * Gets an attribute of a particular element. |
||
438 | * @param string $xml The source xml to parse, this could be the original response received. |
||
439 | * @param string $collection The name of the parent node which wraps the element, if available |
||
440 | * @param string $element The element we need to extract the attribute |
||
441 | * @param string $attr The name of the attribute |
||
442 | */ |
||
443 | |||
444 | public function getAttribute($xml, $collection=NULL, $element=NULL, $attr){ |
||
459 | |||
460 | |||
461 | /** |
||
462 | * Gets set of node values as an array. |
||
463 | * When you get to the depth in the hierarchy use node_child_subchild syntax to get the value. |
||
464 | * @param string $xml The the source xml to parse, this could be the original response received. |
||
465 | * @param string $collection The name of parent node which wraps the elements, if available |
||
466 | * @param string $element The element we need to extract the node values. |
||
467 | */ |
||
468 | |||
469 | public function getValues($xml, $collection=NULL, $element=NULL){ |
||
488 | |||
489 | protected function getRecurseValues($xml,&$data,$parent=""){ |
||
512 | |||
513 | /** |
||
514 | * Gets a single node value. |
||
515 | * @param string $xml The source xml to parse, this could be the original response received. |
||
516 | * @param string $collection The name of parent node which wraps the elements, if available |
||
517 | * @param string $element The element we need to extract the node value. |
||
518 | */ |
||
519 | |||
520 | public function getValue($xml, $collection=NULL, $element=NULL){ |
||
531 | |||
532 | /** |
||
533 | * Searches for a node in document tree and returns it value. |
||
534 | * @param string $xml source xml to parse, this could be the original response received. |
||
535 | * @param string $node Node to search for |
||
536 | */ |
||
537 | public function searchValue($xml, $node=NULL){ |
||
544 | |||
545 | /** |
||
546 | * Searches for a node in document tree and returns its attributes. |
||
547 | * @param string $xml the source xml to parse, this could be the original response received. |
||
548 | * @param string $node Node to search for |
||
549 | */ |
||
550 | public function searchAttributes($xml, $node=NULL){ |
||
568 | } |
||
569 | |||
659 |
Only declaring a single property per statement allows you to later on add doc comments more easily.
It is also recommended by PSR2, so it is a common style that many people expect.