Complex classes like Uri 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 Uri, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
21 | class Uri implements UriInterface |
||
22 | { |
||
23 | /** @var string Uri scheme. */ |
||
24 | protected $scheme = ''; |
||
25 | /** @var string Uri user info. */ |
||
26 | protected $userInfo = ''; |
||
27 | /** @var string Uri host. */ |
||
28 | protected $host = ''; |
||
29 | /** @var int|null Uri port. */ |
||
30 | protected $port = null; |
||
31 | /** @var string Uri path. */ |
||
32 | protected $path = ''; |
||
33 | /** @var string Uri query string. */ |
||
34 | protected $query = ''; |
||
35 | /** @var string Uri fragment. */ |
||
36 | protected $fragment = ''; |
||
37 | |||
38 | /** |
||
39 | * @param string $uri URI to parse and wrap. |
||
40 | */ |
||
41 | 18 | public function __construct($uri = '') |
|
42 | { |
||
43 | 18 | if ('' !== $uri) { |
|
44 | 18 | $parts = parse_url($uri); |
|
45 | //Schema and host should be defined |
||
46 | 18 | if ($parts === false || count($parts) < 2) { |
|
47 | 1 | throw new \InvalidArgumentException("Unable to parse URI: $uri"); |
|
48 | } |
||
49 | 17 | $this->buildFromParts($parts); |
|
50 | 17 | } |
|
51 | 17 | } |
|
52 | |||
53 | /** {@inheritdoc} */ |
||
54 | 4 | public function __toString() |
|
55 | { |
||
56 | 4 | $path = ''; |
|
57 | 4 | if ('' !== $this->getPath()) { |
|
58 | 2 | $path = sprintf('/%s', ltrim($this->getPath(), '/')); |
|
59 | 2 | } |
|
60 | |||
61 | 4 | $query = ''; |
|
62 | 4 | if ('' !== $this->getQuery()) { |
|
63 | 1 | $query = sprintf('?%s', $this->getQuery()); |
|
64 | 1 | } |
|
65 | |||
66 | 4 | $fragment = ''; |
|
67 | 4 | if ('' !== $this->getFragment()) { |
|
68 | 1 | $fragment = sprintf('#%s', $this->getFragment()); |
|
69 | 1 | } |
|
70 | |||
71 | 4 | $uri = sprintf( |
|
72 | 4 | '%s://%s%s%s%s', |
|
73 | 4 | $this->getScheme(), |
|
74 | 4 | $this->getAuthority(), |
|
75 | 4 | $path, |
|
76 | 4 | $query, |
|
77 | $fragment |
||
78 | 4 | ); |
|
79 | |||
80 | 4 | return $uri; |
|
81 | } |
||
82 | |||
83 | /** {@inheritdoc} */ |
||
84 | 4 | public function getScheme() |
|
85 | { |
||
86 | 4 | return $this->scheme; |
|
87 | } |
||
88 | |||
89 | /** {@inheritdoc} */ |
||
90 | 4 | public function getAuthority() |
|
91 | { |
||
92 | 4 | if ('' === $this->host) { |
|
93 | 1 | return ''; |
|
94 | } |
||
95 | |||
96 | 4 | $authority = $this->host; |
|
97 | 4 | if ('' !== $this->userInfo) { |
|
98 | 1 | $authority = sprintf('%s@%s', $this->userInfo, $authority); |
|
99 | 1 | } |
|
100 | |||
101 | 4 | if (null !== $this->port) { |
|
102 | 1 | $authority = sprintf('%s:%d', $authority, $this->port); |
|
103 | 1 | } |
|
104 | |||
105 | 4 | return $authority; |
|
106 | } |
||
107 | |||
108 | /** {@inheritdoc} */ |
||
109 | 1 | public function getUserInfo() |
|
113 | |||
114 | /** {@inheritdoc} */ |
||
115 | 9 | public function getHost() |
|
119 | |||
120 | /** {@inheritdoc} */ |
||
121 | 9 | public function getPort() |
|
125 | |||
126 | /** {@inheritdoc} */ |
||
127 | 5 | public function getPath() |
|
128 | { |
||
129 | 5 | return $this->path; |
|
130 | } |
||
131 | |||
132 | /** {@inheritdoc} */ |
||
133 | 5 | public function getQuery() |
|
137 | |||
138 | /** {@inheritdoc} */ |
||
139 | 4 | public function getFragment() |
|
143 | |||
144 | /** {@inheritdoc} */ |
||
145 | 17 | public function withScheme($scheme) |
|
151 | |||
152 | /** {@inheritdoc} */ |
||
153 | 17 | public function withUserInfo($user, $password = null) |
|
154 | { |
||
155 | 17 | $info = $user; |
|
156 | 17 | if (null !== $password) { |
|
157 | 1 | $info = sprintf('%s:%s', $info, $password); |
|
158 | 1 | } |
|
159 | 17 | $this->userInfo = $info; |
|
160 | |||
161 | 17 | return $this; |
|
162 | } |
||
163 | |||
164 | /** {@inheritdoc} */ |
||
165 | 17 | public function withHost($host) |
|
171 | |||
172 | /** {@inheritdoc} */ |
||
173 | 17 | public function withPort($port) |
|
174 | { |
||
175 | 17 | $this->port = $port; |
|
176 | |||
177 | 17 | return $this; |
|
178 | } |
||
179 | |||
180 | /** {@inheritdoc} */ |
||
181 | 17 | public function withPath($path) |
|
182 | { |
||
183 | 17 | if (!is_string($path)) { |
|
184 | 1 | throw new \InvalidArgumentException( |
|
185 | 'Invalid path provided; must be a string' |
||
186 | 1 | ); |
|
187 | } |
||
188 | 17 | $this->path = $path; |
|
189 | |||
190 | 17 | return $this; |
|
191 | } |
||
192 | |||
193 | /** {@inheritdoc} */ |
||
194 | 17 | public function withQuery($query) |
|
195 | { |
||
196 | 17 | if (!is_string($query) && !is_array($query)) { |
|
197 | 1 | throw new \InvalidArgumentException( |
|
198 | 'Query string must be a string or array' |
||
199 | 1 | ); |
|
200 | } |
||
201 | |||
202 | 17 | if (is_array($query)) { |
|
203 | 1 | $query = http_build_query($query); |
|
204 | 1 | } |
|
205 | |||
206 | 17 | $this->query = ltrim($query, '?'); |
|
207 | |||
208 | 17 | return $this; |
|
209 | } |
||
210 | |||
211 | 17 | public function withFragment($fragment) |
|
217 | |||
218 | /** |
||
219 | * Apply parse_url parts to a URI. |
||
220 | * |
||
221 | * @param $parts array of parse_url parts. |
||
222 | */ |
||
223 | 17 | private function buildFromParts(array $parts) |
|
236 | } |
||
237 |