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 |
||
19 | class FileControllerTest extends RestTestCase |
||
20 | { |
||
21 | /** |
||
22 | * @const complete content type string expected on a resource |
||
23 | */ |
||
24 | const CONTENT_TYPE = 'application/json; charset=UTF-8; profile=http://localhost/schema/file/item'; |
||
25 | |||
26 | /** |
||
27 | * @const corresponding vendorized schema mime type |
||
28 | */ |
||
29 | const COLLECTION_TYPE = 'application/json; charset=UTF-8; profile=http://localhost/schema/file/collection'; |
||
30 | |||
31 | /** |
||
32 | * setup client and load fixtures |
||
33 | * |
||
34 | * @return void |
||
35 | */ |
||
36 | public function setUp() |
||
46 | |||
47 | /** |
||
48 | * check for empty collections when no fixtures are loaded |
||
49 | * |
||
50 | * @return void |
||
51 | */ |
||
52 | View Code Duplication | public function testFindAllEmptyCollection() |
|
66 | |||
67 | /** |
||
68 | * validate that we can post a new file |
||
69 | * |
||
70 | * @return void |
||
71 | */ |
||
72 | public function testPostAndUpdateFile() |
||
73 | { |
||
74 | $fixtureData = file_get_contents(__DIR__.'/fixtures/test.txt'); |
||
75 | $fileHash = hash('sha256', $fixtureData); |
||
76 | $fileHashCustom = 'some-custom-hash-for-testing'; |
||
77 | |||
78 | $client = static::createRestClient(); |
||
79 | $client->post( |
||
80 | '/file/', |
||
81 | $fixtureData, |
||
82 | [], |
||
83 | [], |
||
84 | ['CONTENT_TYPE' => 'text/plain'], |
||
85 | false |
||
86 | ); |
||
87 | $this->assertEmpty($client->getResults()); |
||
88 | $response = $client->getResponse(); |
||
89 | $this->assertEquals(201, $response->getStatusCode()); |
||
90 | |||
91 | $fileLocation = $response->headers->get('Location'); |
||
92 | |||
93 | // update file contents to update mod date |
||
94 | $client = static::createRestClient(); |
||
95 | $client->put( |
||
96 | $fileLocation, |
||
97 | $fixtureData, |
||
98 | [], |
||
99 | [], |
||
100 | ['CONTENT_TYPE' => 'text/plain'], |
||
101 | false |
||
102 | ); |
||
103 | $this->assertEmpty($client->getResults(), $client->getResponse()->getContent()); |
||
104 | $response = $client->getResponse(); |
||
105 | $this->assertEquals(204, $response->getStatusCode()); |
||
106 | |||
107 | $client = static::createRestClient(); |
||
108 | $client->request('GET', $fileLocation); |
||
109 | $data = $client->getResults(); |
||
110 | |||
111 | // check for valid format |
||
112 | $this->assertNotFalse(\DateTime::createFromFormat(\DateTime::RFC3339, $data->metadata->createDate)); |
||
113 | $this->assertNotFalse(\DateTime::createFromFormat(\DateTime::RFC3339, $data->metadata->modificationDate)); |
||
114 | // Check valid hash encoding if no hash sent |
||
115 | $this->assertEquals($fileHash, $data->metadata->hash); |
||
116 | |||
117 | $data->links = []; |
||
118 | $link = new \stdClass; |
||
119 | $link->{'$ref'} = 'http://localhost/core/app/tablet'; |
||
120 | $data->links[] = $link; |
||
121 | |||
122 | $filename = "test.txt"; |
||
123 | $data->metadata->filename = $filename; |
||
124 | $data->metadata->hash = $fileHashCustom; |
||
125 | |||
126 | $client = static::createRestClient(); |
||
127 | $client->put(sprintf('/file/%s', $data->id), $data); |
||
128 | |||
129 | // re-fetch |
||
130 | $client = static::createRestClient(); |
||
131 | $client->request('GET', sprintf('/file/%s', $data->id)); |
||
132 | $results = $client->getResults(); |
||
133 | |||
134 | $this->assertEquals($link->{'$ref'}, $results->links[0]->{'$ref'}); |
||
135 | $this->assertEquals($filename, $results->metadata->filename); |
||
136 | $this->assertEquals($fileHashCustom, $data->metadata->hash); |
||
137 | |||
138 | $client = static::createClient(); |
||
139 | $client->request('GET', sprintf('/file/%s', $data->id), [], [], ['HTTP_ACCEPT' => 'text/plain']); |
||
140 | |||
141 | $results = $client->getResponse()->getContent(); |
||
142 | |||
143 | $this->assertEquals($fixtureData, $results); |
||
144 | |||
145 | // change link and add second link |
||
146 | $data->links[0]->{'$ref'} = 'http://localhost/core/app/admin'; |
||
147 | $link = new \stdClass; |
||
148 | $link->{'$ref'} = 'http://localhost/core/app/web'; |
||
149 | $data->links[] = $link; |
||
150 | |||
151 | // also add action command |
||
152 | $command = new \stdClass(); |
||
153 | $command->command = 'print'; |
||
154 | $data->metadata->action = [$command]; |
||
155 | |||
156 | // also add additionalInformation |
||
157 | $data->metadata->additionalInformation = 'someInfo'; |
||
158 | |||
159 | $client = static::createRestClient(); |
||
160 | $client->put(sprintf('/file/%s', $data->id), $data); |
||
161 | |||
162 | // re-fetch |
||
163 | $client = static::createRestClient(); |
||
164 | $client->request('GET', sprintf('/file/%s', $data->id)); |
||
165 | $results = $client->getResults(); |
||
166 | |||
167 | $this->assertEquals($data->links[0]->{'$ref'}, $results->links[0]->{'$ref'}); |
||
168 | $this->assertEquals($data->links[1]->{'$ref'}, $results->links[1]->{'$ref'}); |
||
169 | |||
170 | // check metadata |
||
171 | $this->assertEquals(18, $data->metadata->size); |
||
172 | $this->assertEquals('text/plain', $data->metadata->mime); |
||
173 | $this->assertEquals('test.txt', $data->metadata->filename); |
||
174 | $this->assertEquals('print', $data->metadata->action[0]->command); |
||
175 | $this->assertEquals('someInfo', $data->metadata->additionalInformation); |
||
176 | $this->assertNotNull($data->metadata->createDate); |
||
177 | $this->assertNotNull($data->metadata->modificationDate); |
||
178 | |||
179 | // remove a link |
||
180 | unset($data->links[1]); |
||
181 | |||
182 | $client = static::createRestClient(); |
||
183 | $client->put(sprintf('/file/%s', $data->id), $data); |
||
184 | // re-fetch |
||
185 | $client = static::createRestClient(); |
||
186 | $client->request('GET', sprintf('/file/%s', $data->id)); |
||
187 | $results = $client->getResults(); |
||
188 | |||
189 | $this->assertEquals($data->links[0]->{'$ref'}, $results->links[0]->{'$ref'}); |
||
190 | $this->assertCount(1, $results->links); |
||
191 | |||
192 | // remove last link |
||
193 | $data->links = []; |
||
194 | $client = static::createRestClient(); |
||
195 | $client->put(sprintf('/file/%s', $data->id), $data); |
||
196 | |||
197 | // re-fetch |
||
198 | $client = static::createRestClient(); |
||
199 | $client->request('GET', sprintf('/file/%s', $data->id)); |
||
200 | |||
201 | $results = $client->getResults(); |
||
202 | |||
203 | $this->assertEmpty($results->links); |
||
204 | |||
205 | // Let's update links but without sending file and still have file info |
||
206 | $id = $data->id; |
||
207 | $data = new \stdClass; |
||
208 | $data->id = $id; |
||
209 | $link = new \stdClass; |
||
210 | $link->{'$ref'} = 'http://localhost/core/app/web'; |
||
211 | $data->links = []; |
||
212 | $data->links[] = $link; |
||
213 | $client = static::createRestClient(); |
||
214 | $client->put(sprintf('/file/%s', $id), $data); |
||
215 | // re-fetch |
||
216 | $client = static::createRestClient(); |
||
217 | $client->request('GET', sprintf('/file/%s', $data->id)); |
||
218 | $data = $client->getResults(); |
||
219 | // check metadata for kept file info |
||
220 | $this->assertEquals(18, $data->metadata->size); |
||
221 | $this->assertEquals('text/plain', $data->metadata->mime); |
||
222 | $this->assertEquals('test.txt', $data->metadata->filename); |
||
223 | $this->assertNotNull($data->metadata->createDate); |
||
224 | $this->assertNotNull($data->metadata->modificationDate); |
||
225 | } |
||
226 | |||
227 | /** |
||
228 | * validate that we can post a new file |
||
229 | * |
||
230 | * @return void |
||
231 | */ |
||
232 | View Code Duplication | public function testPostNewFile() |
|
251 | |||
252 | /** |
||
253 | * validate that we can put a new file with a custom id |
||
254 | * |
||
255 | * @return void |
||
256 | */ |
||
257 | View Code Duplication | public function testPutNewFile() |
|
276 | |||
277 | /** |
||
278 | * validate that we can delete a file |
||
279 | * |
||
280 | * @return void |
||
281 | */ |
||
282 | public function testDeleteFile() |
||
311 | |||
312 | /** |
||
313 | * validate that we can update the content from a file |
||
314 | * |
||
315 | * @return void |
||
316 | */ |
||
317 | public function testUpdateFileContent() |
||
348 | |||
349 | /** |
||
350 | * post a file without any mime type.. check if that mime type is correctly determined. |
||
351 | * fetch content back and compare the contents of the file |
||
352 | * |
||
353 | * @return void |
||
354 | */ |
||
355 | public function testPostFileContentMimeDetectionAndContent() |
||
397 | |||
398 | /** |
||
399 | * here we PUT a file, then try to update the mimetype in the metadata |
||
400 | * to 'something/other' and see if we can still GET it and receive the correct mime type |
||
401 | * (meaning we were not able to modify the mime type) |
||
402 | * |
||
403 | * @return void |
||
404 | */ |
||
405 | public function testIllegalMimeTypeModificationHandling() |
||
406 | { |
||
407 | $fileData = "This is a new text!!!"; |
||
408 | $contentType = 'text/plain'; |
||
409 | |||
410 | $client = static::createRestClient(); |
||
411 | $client->put( |
||
412 | '/file/mimefile', |
||
413 | $fileData, |
||
414 | [], |
||
415 | [], |
||
416 | [], |
||
417 | [], |
||
418 | false |
||
419 | ); |
||
420 | $response = $client->getResponse(); |
||
421 | $this->assertEquals(Response::HTTP_NO_CONTENT, $response->getStatusCode()); |
||
422 | |||
423 | // GET the metadata |
||
424 | $client = static::createRestClient(); |
||
425 | $client->request('GET', '/file/mimefile'); |
||
426 | $retData = $client->getResults(); |
||
427 | |||
428 | $this->assertEquals($retData->metadata->mime, $contentType); |
||
429 | |||
430 | // change metadata and save |
||
431 | $retData->metadata->mime = 'something/other'; |
||
432 | |||
433 | $client = static::createRestClient(); |
||
434 | $client->put('/file/mimefile', $retData); |
||
435 | |||
436 | $client = static::createClient(); |
||
437 | $client->request( |
||
438 | 'GET', |
||
439 | '/file/mimefile', |
||
440 | [], |
||
441 | [], |
||
442 | ['ACCEPT' => '*/*'] |
||
443 | ); |
||
444 | |||
445 | $response = $client->getInternalResponse(); |
||
446 | |||
447 | // still the good one? |
||
448 | $this->assertContains($contentType, $response->getHeader('content-type')); |
||
449 | |||
450 | $client = static::createRestClient(); |
||
451 | $client->request('DELETE', '/file/mimefile'); |
||
452 | } |
||
453 | |||
454 | /** |
||
455 | * test getting collection schema |
||
456 | * |
||
457 | * @return void |
||
458 | */ |
||
459 | public function testGetFileCollectionSchemaInformation() |
||
486 | |||
487 | /** |
||
488 | * test behavior when data sent was multipart/form-data |
||
489 | * |
||
490 | * @return void |
||
491 | */ |
||
492 | public function testPutNewFileViaForm() |
||
567 | |||
568 | /** |
||
569 | * test behavior when data sent was multipart/form-data |
||
570 | * |
||
571 | * @return void |
||
572 | */ |
||
573 | public function testPutNewFileViaFormHashToLong() |
||
632 | |||
633 | |||
634 | |||
635 | /** |
||
636 | /** |
||
637 | * test behavior when data sent was multipart/form-data |
||
638 | * |
||
639 | * @return void |
||
640 | */ |
||
641 | public function testPutNewJsonFileViaForm() |
||
672 | |||
673 | /** |
||
674 | * check if a schema is of the file type |
||
675 | * |
||
676 | * @param \stdClass $schema schema from service to validate |
||
677 | * |
||
678 | * @return void |
||
679 | */ |
||
680 | private function assertIsFileSchema(\stdClass $schema) |
||
814 | |||
815 | /** |
||
816 | * Verifies the update of a file content. |
||
817 | * |
||
818 | * @param string $fileId identifier of the file to be updated |
||
819 | * @param string $newContent new content to be stored in the file |
||
820 | * @param string $contentType Content-Type of the file |
||
821 | * |
||
822 | * @return null|Response |
||
823 | */ |
||
824 | private function updateFileContent($fileId, $newContent, $contentType = 'text/plain') |
||
846 | } |
||
847 |
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.