Duplicate code is one of the most pungent code smells. A rule that is often used is to re-structure code once it is duplicated in three or more places.
Common duplication problems, and corresponding solutions are:
1 | <?php |
||
35 | class ContentApiSdk |
||
36 | { |
||
37 | /** |
||
38 | * Items endpoint |
||
39 | */ |
||
40 | const SUPERDESK_ENDPOINT_ITEMS = '/items'; |
||
41 | |||
42 | /** |
||
43 | * Package endpoint |
||
44 | */ |
||
45 | const SUPERDESK_ENDPOINT_PACKAGES = '/packages'; |
||
46 | |||
47 | /** |
||
48 | * Type indication for packages |
||
49 | */ |
||
50 | const PACKAGE_TYPE_COMPOSITE = 'composite'; |
||
51 | |||
52 | /** |
||
53 | * Supported API version by this SDK version |
||
54 | */ |
||
55 | const API_VERSION = 1; |
||
56 | |||
57 | /** |
||
58 | * Useragent string sent to the API when making requests. |
||
59 | */ |
||
60 | const USERAGENT = 'Content API SDK v1'; |
||
61 | |||
62 | /** |
||
63 | * Any (http) client that implements ClientInterface. |
||
64 | * |
||
65 | * @var ApiClientInterface |
||
66 | */ |
||
67 | protected $client; |
||
68 | |||
69 | /** |
||
70 | * Protocol to reach the api instance. |
||
71 | * |
||
72 | * @var string|null |
||
73 | */ |
||
74 | protected $protocol = null; |
||
75 | |||
76 | /** |
||
77 | * Hostname of the api instance. |
||
78 | * |
||
79 | * @var string|null |
||
80 | */ |
||
81 | protected $host = null; |
||
82 | |||
83 | /** |
||
84 | * Port of the api instance. |
||
85 | * |
||
86 | * @var int|null |
||
87 | */ |
||
88 | protected $port = null; |
||
89 | |||
90 | /** |
||
91 | * Authentication object. |
||
92 | * |
||
93 | * @var AuthenticationInterface |
||
94 | */ |
||
95 | protected $authentication = null; |
||
96 | |||
97 | /** |
||
98 | * Construct method for class. |
||
99 | * |
||
100 | * @param ApiClientInterface $client |
||
101 | * @param string|null $host |
||
102 | * @param int|null $port |
||
103 | * @param string|null $protocol |
||
104 | */ |
||
105 | public function __construct( |
||
106 | ApiClientInterface $client, |
||
107 | $host = null, |
||
108 | $port = null, |
||
109 | $protocol = null |
||
110 | ) { |
||
111 | $this->client = $client; |
||
112 | |||
113 | if (!is_null($host)) { |
||
114 | $this->setHost($host); |
||
115 | } |
||
116 | |||
117 | if (!is_null($port)) { |
||
118 | $this->setPort($port); |
||
119 | } |
||
120 | |||
121 | if (!is_null($protocol)) { |
||
122 | $this->setProtocol($protocol); |
||
123 | } |
||
124 | } |
||
125 | |||
126 | /** |
||
127 | * Gets the value of client. |
||
128 | * |
||
129 | * @return ApiClientInterface |
||
130 | */ |
||
131 | public function getClient() |
||
132 | { |
||
133 | return $this->client; |
||
134 | } |
||
135 | |||
136 | /** |
||
137 | * Sets the value of client. |
||
138 | * |
||
139 | * @param ApiClientInterface $client Value to set |
||
140 | * |
||
141 | * @return self |
||
142 | */ |
||
143 | public function setClient(ApiClientInterface $client) |
||
144 | { |
||
145 | $this->client = $client; |
||
146 | |||
147 | return $this; |
||
148 | } |
||
149 | |||
150 | /** |
||
151 | * Gets the value of apiHost. |
||
152 | * |
||
153 | * @return string|null |
||
154 | */ |
||
155 | public function getHost() |
||
156 | { |
||
157 | return $this->host; |
||
158 | } |
||
159 | |||
160 | /** |
||
161 | * Sets the value of host. |
||
162 | * |
||
163 | * @param string|null $host Value to set |
||
164 | * |
||
165 | * @return self |
||
166 | */ |
||
167 | public function setHost($host) |
||
168 | { |
||
169 | $this->host = $host; |
||
170 | |||
171 | return $this; |
||
172 | } |
||
173 | |||
174 | /** |
||
175 | * Gets the value of port. |
||
176 | * |
||
177 | * @return int|null |
||
178 | */ |
||
179 | public function getPort() |
||
180 | { |
||
181 | return $this->port; |
||
182 | } |
||
183 | |||
184 | /** |
||
185 | * Sets the value of port. |
||
186 | * |
||
187 | * @param int|null $port Value to set |
||
188 | * |
||
189 | * @return self |
||
190 | */ |
||
191 | public function setPort($port) |
||
192 | { |
||
193 | $this->port = $port; |
||
194 | |||
195 | return $this; |
||
196 | } |
||
197 | |||
198 | /** |
||
199 | * Gets the value of protocol. |
||
200 | * |
||
201 | * @return string|null |
||
202 | */ |
||
203 | public function getProtocol() |
||
204 | { |
||
205 | return $this->protocol; |
||
206 | } |
||
207 | |||
208 | /** |
||
209 | * Sets the value of protocol. |
||
210 | * |
||
211 | * @param string|null $protocol Value to set |
||
212 | * |
||
213 | * @return self |
||
214 | */ |
||
215 | public function setProtocol($protocol) |
||
216 | { |
||
217 | $this->protocol = $protocol; |
||
218 | |||
219 | return $this; |
||
220 | } |
||
221 | |||
222 | /** |
||
223 | * Get a single item via id. |
||
224 | * |
||
225 | * @param string $itemId Identifier for item |
||
226 | * |
||
227 | * @return Item |
||
228 | */ |
||
229 | public function getItem($itemId) |
||
230 | { |
||
231 | $request = $this->getNewRequest(sprintf('%s/%s', self::SUPERDESK_ENDPOINT_ITEMS, $itemId)); |
||
232 | |||
233 | try { |
||
234 | $response = $this->client->makeApiCall($request); |
||
235 | $item = new Item($response->getResources()); |
||
236 | |||
237 | return $item; |
||
238 | } catch (ClientException $e) { |
||
239 | throw new ContentApiException($e->getMessage(), $e->getCode(), $e); |
||
240 | } |
||
241 | } |
||
242 | |||
243 | /** |
||
244 | * Get multiple items based on a filter. |
||
245 | * |
||
246 | * @param array $params Filter parameters |
||
247 | * @param int $page Page to return |
||
248 | * @param int $maxResults Maximum amount of packages a page |
||
249 | * |
||
250 | * @return ResourceCollection |
||
251 | */ |
||
252 | View Code Duplication | public function getItems($params, $page = 1, $maxResults = 25) |
|
|
|||
253 | { |
||
254 | $itemCollection = new ResourceCollection( |
||
255 | new ItemAdapter( |
||
256 | $this->client, |
||
257 | $this->getNewRequest(self::SUPERDESK_ENDPOINT_ITEMS, $params) |
||
258 | ) |
||
259 | ); |
||
260 | |||
261 | $itemCollection->setCurrentPage($page); |
||
262 | $itemCollection->setMaxPerPage($maxResults); |
||
263 | |||
264 | return $itemCollection; |
||
265 | } |
||
266 | |||
267 | /** |
||
268 | * Get package by identifier. |
||
269 | * |
||
270 | * @param string $packageId Package identifier |
||
271 | * @param bool $resolveAssociations Inject full associations recursively |
||
272 | * instead of references by uri. |
||
273 | * |
||
274 | * @return Package |
||
275 | */ |
||
276 | public function getPackage($packageId, $resolveAssociations = false) |
||
277 | { |
||
278 | $request = $this->getNewRequest(sprintf('%s/%s', self::SUPERDESK_ENDPOINT_PACKAGES, $packageId)); |
||
279 | $response = $this->client->makeApiCall($request); |
||
280 | |||
281 | $package = new Package($response->getResources()); |
||
282 | |||
283 | // This can be removed once the API fully supports retrieving package associations |
||
284 | if ($resolveAssociations) { |
||
285 | $associations = $this->getAssociationsFromPackage($package); |
||
286 | $package = $this->injectAssociations($package, $associations); |
||
287 | } |
||
288 | |||
289 | return $package; |
||
290 | } |
||
291 | |||
292 | /** |
||
293 | * Get multiple packages based on a filter. |
||
294 | * |
||
295 | * @param array $params Filter parameters |
||
296 | * @param bool $resolveAssociations Inject full associations recursively |
||
297 | * instead of references by uri. |
||
298 | * @param int $page Page to return |
||
299 | * @param int $maxResults Maximum amount of packages a page |
||
300 | * |
||
301 | * @return ResourceCollection |
||
302 | */ |
||
303 | View Code Duplication | public function getPackages( |
|
304 | $params, |
||
305 | $resolveAssociations = false, |
||
306 | $page = 1, |
||
307 | $maxResults = 25 |
||
308 | ) { |
||
309 | $packageCollection = new ResourceCollection( |
||
310 | new PackageAdapter( |
||
311 | $this->client, |
||
312 | $this->getNewRequest(self::SUPERDESK_ENDPOINT_PACKAGES, $params), |
||
313 | $this, |
||
314 | $resolveAssociations |
||
315 | ) |
||
316 | ); |
||
317 | |||
318 | $packageCollection->setCurrentPage($page); |
||
319 | $packageCollection->setMaxPerPage($maxResults); |
||
320 | |||
321 | return $packageCollection; |
||
322 | } |
||
323 | |||
324 | /** |
||
325 | * Gets full objects for all associations for a package. |
||
326 | * |
||
327 | * @param Package $package A package |
||
328 | * |
||
329 | * @return stdClass List of associations |
||
330 | */ |
||
331 | public function getAssociationsFromPackage(Package $package) |
||
363 | |||
364 | /** |
||
365 | * Overwrite the associations links in a packages with the actual association |
||
366 | * data. |
||
367 | * |
||
368 | * @param Package $package Package |
||
369 | * @param stdClass $associations Multiple items or packages |
||
370 | * |
||
371 | * @return Package Package with data injected |
||
372 | */ |
||
373 | public function injectAssociations(Package $package, stdClass $associations) |
||
381 | |||
382 | /** |
||
383 | * Shortcut method to create new class. |
||
384 | * |
||
385 | * @param string $uri Uri of the request |
||
386 | * @param array $parameters Parameters for the request object |
||
387 | * |
||
388 | * @return Request |
||
389 | */ |
||
390 | public function getNewRequest($uri, array $parameters = array()) |
||
391 | { |
||
392 | try { |
||
393 | $request = new Request($this->host, $uri, $parameters, $this->port, $this->protocol); |
||
394 | } catch (ContentApiException $e) { |
||
400 | |||
401 | /** |
||
402 | * Tries to find a valid id in an uri, both item as package uris. The id |
||
403 | * is returned urldecoded. |
||
404 | * |
||
405 | * @param string $uri Item or package uri |
||
406 | * |
||
407 | * @return string Urldecoded id |
||
408 | */ |
||
409 | public static function getIdFromUri($uri) |
||
425 | |||
426 | /** |
||
427 | * Returns a list of all supported endpoints for the Superdesk Content API. |
||
428 | * |
||
429 | * @return string[] |
||
430 | */ |
||
431 | public static function getAvailableEndpoints() |
||
438 | |||
439 | /** |
||
440 | * Converts json string into StdClass object. Throws an InvalidDataException |
||
441 | * when string could not be converted to object. |
||
442 | * |
||
443 | * @param string $jsonString JSON string |
||
444 | * |
||
445 | * @return object |
||
446 | * @throws Exception|InvalidDataException |
||
447 | */ |
||
448 | public static function getValidJsonObj($jsonString) |
||
457 | |||
458 | /** |
||
459 | * Returns version of api for creating verioned url. |
||
460 | * |
||
461 | * @return string |
||
462 | */ |
||
463 | public static function getVersionURL() |
||
467 | } |
||
468 |
Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.
You can also find more detailed suggestions in the “Code” section of your repository.