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:
Complex classes like WP_Test_REST_Attachments_Controller 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 WP_Test_REST_Attachments_Controller, and based on these observations, apply Extract Interface, too.
1 | <?php |
||
9 | class WP_Test_REST_Attachments_Controller extends WP_Test_REST_Post_Type_Controller_Testcase { |
||
10 | |||
11 | public function setUp() { |
||
12 | parent::setUp(); |
||
13 | |||
14 | $this->editor_id = $this->factory->user->create( array( |
||
15 | 'role' => 'editor', |
||
16 | ) ); |
||
17 | $this->author_id = $this->factory->user->create( array( |
||
18 | 'role' => 'author', |
||
19 | ) ); |
||
20 | $this->contributor_id = $this->factory->user->create( array( |
||
21 | 'role' => 'contributor', |
||
22 | ) ); |
||
23 | |||
24 | $orig_file = dirname( __FILE__ ) . '/data/canola.jpg'; |
||
25 | $this->test_file = '/tmp/canola.jpg'; |
||
26 | copy( $orig_file, $this->test_file ); |
||
27 | $orig_file2 = dirname( __FILE__ ) . '/data/codeispoetry.png'; |
||
28 | $this->test_file2 = '/tmp/codeispoetry.png'; |
||
29 | copy( $orig_file2, $this->test_file2 ); |
||
30 | |||
31 | } |
||
32 | |||
33 | View Code Duplication | public function test_register_routes() { |
|
40 | |||
41 | public static function disposition_provider() { |
||
72 | |||
73 | /** |
||
74 | * @dataProvider disposition_provider |
||
75 | */ |
||
76 | public function test_parse_disposition( $header, $expected ) { |
||
81 | |||
82 | public function test_context_param() { |
||
100 | |||
101 | public function test_registered_query_params() { |
||
102 | $request = new WP_REST_Request( 'OPTIONS', '/wp/v2/media' ); |
||
103 | $response = $this->server->dispatch( $request ); |
||
104 | $data = $response->get_data(); |
||
105 | $keys = array_keys( $data['endpoints'][0]['args'] ); |
||
106 | sort( $keys ); |
||
107 | $this->assertEquals( array( |
||
108 | 'after', |
||
109 | 'author', |
||
110 | 'author_exclude', |
||
111 | 'before', |
||
112 | 'context', |
||
113 | 'exclude', |
||
114 | 'filter', |
||
115 | 'include', |
||
116 | 'media_type', |
||
117 | 'mime_type', |
||
118 | 'offset', |
||
119 | 'order', |
||
120 | 'orderby', |
||
121 | 'page', |
||
122 | 'parent', |
||
123 | 'parent_exclude', |
||
124 | 'per_page', |
||
125 | 'search', |
||
126 | 'slug', |
||
127 | 'status', |
||
128 | ), $keys ); |
||
129 | $media_types = array( |
||
130 | 'application', |
||
131 | 'video', |
||
132 | 'image', |
||
133 | 'audio', |
||
134 | ); |
||
135 | if ( ! is_multisite() ) { |
||
136 | $media_types[] = 'text'; |
||
137 | } |
||
138 | $this->assertEqualSets( $media_types, $data['endpoints'][0]['args']['media_type']['enum'] ); |
||
139 | } |
||
140 | |||
141 | View Code Duplication | public function test_get_items() { |
|
168 | |||
169 | View Code Duplication | public function test_get_items_logged_in_editor() { |
|
195 | |||
196 | View Code Duplication | public function test_get_items_media_type() { |
|
197 | $id1 = $this->factory->attachment->create_object( $this->test_file, 0, array( |
||
198 | 'post_mime_type' => 'image/jpeg', |
||
199 | ) ); |
||
200 | $request = new WP_REST_Request( 'GET', '/wp/v2/media' ); |
||
201 | $response = $this->server->dispatch( $request ); |
||
202 | $data = $response->get_data(); |
||
203 | $this->assertEquals( $id1, $data[0]['id'] ); |
||
204 | // media_type=video |
||
205 | $request->set_param( 'media_type', 'video' ); |
||
206 | $response = $this->server->dispatch( $request ); |
||
207 | $this->assertCount( 0, $response->get_data() ); |
||
208 | // media_type=image |
||
209 | $request->set_param( 'media_type', 'image' ); |
||
210 | $response = $this->server->dispatch( $request ); |
||
211 | $data = $response->get_data(); |
||
212 | $this->assertEquals( $id1, $data[0]['id'] ); |
||
213 | } |
||
214 | |||
215 | View Code Duplication | public function test_get_items_mime_type() { |
|
216 | $id1 = $this->factory->attachment->create_object( $this->test_file, 0, array( |
||
217 | 'post_mime_type' => 'image/jpeg', |
||
218 | ) ); |
||
219 | $request = new WP_REST_Request( 'GET', '/wp/v2/media' ); |
||
220 | $response = $this->server->dispatch( $request ); |
||
221 | $data = $response->get_data(); |
||
222 | $this->assertEquals( $id1, $data[0]['id'] ); |
||
223 | // mime_type=image/png |
||
224 | $request->set_param( 'mime_type', 'image/png' ); |
||
225 | $response = $this->server->dispatch( $request ); |
||
226 | $this->assertCount( 0, $response->get_data() ); |
||
227 | // mime_type=image/jpeg |
||
228 | $request->set_param( 'mime_type', 'image/jpeg' ); |
||
229 | $response = $this->server->dispatch( $request ); |
||
230 | $data = $response->get_data(); |
||
231 | $this->assertEquals( $id1, $data[0]['id'] ); |
||
232 | } |
||
233 | |||
234 | public function test_get_items_parent() { |
||
235 | $post_id = $this->factory->post->create( array( 'post_title' => 'Test Post' ) ); |
||
236 | $attachment_id = $this->factory->attachment->create_object( $this->test_file, $post_id, array( |
||
237 | 'post_mime_type' => 'image/jpeg', |
||
238 | 'post_excerpt' => 'A sample caption', |
||
239 | ) ); |
||
240 | $attachment_id2 = $this->factory->attachment->create_object( $this->test_file, 0, array( |
||
241 | 'post_mime_type' => 'image/jpeg', |
||
242 | 'post_excerpt' => 'A sample caption', |
||
243 | ) ); |
||
244 | // all attachments |
||
245 | $request = new WP_REST_Request( 'GET', '/wp/v2/media' ); |
||
246 | $response = $this->server->dispatch( $request ); |
||
247 | $this->assertEquals( 2, count( $response->get_data() ) ); |
||
248 | $request = new WP_REST_Request( 'GET', '/wp/v2/media' ); |
||
249 | // attachments without a parent |
||
250 | $request->set_param( 'parent', 0 ); |
||
251 | $response = $this->server->dispatch( $request ); |
||
252 | $data = $response->get_data(); |
||
253 | $this->assertEquals( 1, count( $data ) ); |
||
254 | $this->assertEquals( $attachment_id2, $data[0]['id'] ); |
||
255 | // attachments with parent=post_id |
||
256 | $request = new WP_REST_Request( 'GET', '/wp/v2/media' ); |
||
257 | $request->set_param( 'parent', $post_id ); |
||
258 | $response = $this->server->dispatch( $request ); |
||
259 | $data = $response->get_data(); |
||
260 | $this->assertEquals( 1, count( $data ) ); |
||
261 | $this->assertEquals( $attachment_id, $data[0]['id'] ); |
||
262 | // attachments with invalid parent |
||
263 | $request = new WP_REST_Request( 'GET', '/wp/v2/media' ); |
||
264 | $request->set_param( 'parent', REST_TESTS_IMPOSSIBLY_HIGH_NUMBER ); |
||
265 | $response = $this->server->dispatch( $request ); |
||
266 | $data = $response->get_data(); |
||
267 | $this->assertEquals( 0, count( $data ) ); |
||
268 | } |
||
269 | |||
270 | public function test_get_items_invalid_status_param_is_discarded() { |
||
271 | wp_set_current_user( $this->editor_id ); |
||
272 | $this->factory->attachment->create_object( $this->test_file, 0, array( |
||
273 | 'post_mime_type' => 'image/jpeg', |
||
274 | 'post_excerpt' => 'A sample caption', |
||
275 | ) ); |
||
276 | $request = new WP_REST_Request( 'GET', '/wp/v2/media' ); |
||
277 | $request->set_param( 'status', 'publish' ); |
||
278 | $request->set_param( 'context', 'edit' ); |
||
279 | $response = $this->server->dispatch( $request ); |
||
280 | $data = $response->get_data(); |
||
281 | $this->assertCount( 1, $data ); |
||
282 | $this->assertEquals( 'inherit', $data[0]['status'] ); |
||
283 | } |
||
284 | |||
285 | public function test_get_items_private_status() { |
||
304 | |||
305 | View Code Duplication | public function test_get_items_invalid_date() { |
|
306 | $request = new WP_REST_Request( 'GET', '/wp/v2/media' ); |
||
307 | $request->set_param( 'after', rand_str() ); |
||
308 | $request->set_param( 'before', rand_str() ); |
||
309 | $response = $this->server->dispatch( $request ); |
||
310 | $this->assertErrorResponse( 'rest_invalid_param', $response, 400 ); |
||
311 | } |
||
312 | |||
313 | public function test_get_items_valid_date() { |
||
314 | $id1 = $this->factory->attachment->create_object( $this->test_file, 0, array( |
||
|
|||
315 | 'post_date' => '2016-01-15T00:00:00Z', |
||
316 | 'post_mime_type' => 'image/jpeg', |
||
317 | 'post_excerpt' => 'A sample caption', |
||
318 | ) ); |
||
319 | $id2 = $this->factory->attachment->create_object( $this->test_file, 0, array( |
||
320 | 'post_date' => '2016-01-16T00:00:00Z', |
||
321 | 'post_mime_type' => 'image/jpeg', |
||
322 | 'post_excerpt' => 'A sample caption', |
||
323 | ) ); |
||
324 | $id3 = $this->factory->attachment->create_object( $this->test_file, 0, array( |
||
325 | 'post_date' => '2016-01-17T00:00:00Z', |
||
326 | 'post_mime_type' => 'image/jpeg', |
||
327 | 'post_excerpt' => 'A sample caption', |
||
328 | ) ); |
||
329 | $request = new WP_REST_Request( 'GET', '/wp/v2/media' ); |
||
330 | $request->set_param( 'after', '2016-01-15T00:00:00Z' ); |
||
331 | $request->set_param( 'before', '2016-01-17T00:00:00Z' ); |
||
332 | $response = $this->server->dispatch( $request ); |
||
333 | $data = $response->get_data(); |
||
334 | $this->assertCount( 1, $data ); |
||
335 | $this->assertEquals( $id2, $data[0]['id'] ); |
||
336 | } |
||
337 | |||
338 | View Code Duplication | public function test_get_item() { |
|
339 | $attachment_id = $this->factory->attachment->create_object( $this->test_file, 0, array( |
||
340 | 'post_mime_type' => 'image/jpeg', |
||
341 | 'post_excerpt' => 'A sample caption', |
||
342 | ) ); |
||
343 | update_post_meta( $attachment_id, '_wp_attachment_image_alt', 'Sample alt text' ); |
||
344 | $request = new WP_REST_Request( 'GET', '/wp/v2/media/' . $attachment_id ); |
||
345 | $response = $this->server->dispatch( $request ); |
||
346 | $this->check_get_post_response( $response ); |
||
347 | $data = $response->get_data(); |
||
348 | $this->assertEquals( 'image/jpeg', $data['mime_type'] ); |
||
349 | } |
||
350 | |||
351 | public function test_get_item_sizes() { |
||
372 | |||
373 | public function test_get_item_sizes_with_no_url() { |
||
392 | |||
393 | View Code Duplication | public function test_get_item_private_post() { |
|
404 | |||
405 | public function test_create_item() { |
||
418 | |||
419 | public function test_create_item_default_filename_title() { |
||
420 | wp_set_current_user( $this->author_id ); |
||
421 | $request = new WP_REST_Request( 'POST', '/wp/v2/media' ); |
||
422 | $request->set_file_params( array( |
||
423 | 'file' => array( |
||
424 | 'file' => file_get_contents( $this->test_file2 ), |
||
425 | 'name' => 'codeispoetry.jpg', |
||
426 | 'size' => filesize( $this->test_file2 ), |
||
427 | 'tmp_name' => $this->test_file2, |
||
428 | ), |
||
429 | ) ); |
||
430 | $request->set_header( 'Content-MD5', md5_file( $this->test_file2 ) ); |
||
431 | $response = $this->server->dispatch( $request ); |
||
432 | $this->assertEquals( 201, $response->get_status() ); |
||
433 | $data = $response->get_data(); |
||
434 | $this->assertEquals( 'codeispoetry', $data['title']['raw'] ); |
||
435 | } |
||
436 | |||
437 | View Code Duplication | public function test_create_item_with_files() { |
|
452 | |||
453 | public function test_create_item_empty_body() { |
||
459 | |||
460 | public function test_create_item_missing_content_type() { |
||
467 | |||
468 | public function test_create_item_missing_content_disposition() { |
||
476 | |||
477 | View Code Duplication | public function test_create_item_bad_md5_header() { |
|
487 | |||
488 | View Code Duplication | public function test_create_item_with_files_bad_md5_header() { |
|
503 | |||
504 | public function test_create_item_invalid_upload_files_capability() { |
||
510 | |||
511 | public function test_create_item_invalid_edit_permissions() { |
||
519 | |||
520 | View Code Duplication | public function test_create_item_invalid_post_type() { |
|
531 | |||
532 | View Code Duplication | public function test_create_item_alt_text() { |
|
544 | |||
545 | View Code Duplication | public function test_create_item_unsafe_alt_text() { |
|
556 | |||
557 | public function test_update_item() { |
||
558 | wp_set_current_user( $this->editor_id ); |
||
559 | $attachment_id = $this->factory->attachment->create_object( $this->test_file, 0, array( |
||
560 | 'post_mime_type' => 'image/jpeg', |
||
561 | 'post_excerpt' => 'A sample caption', |
||
562 | 'post_author' => $this->editor_id, |
||
563 | ) ); |
||
564 | $request = new WP_REST_Request( 'POST', '/wp/v2/media/' . $attachment_id ); |
||
565 | $request->set_param( 'title', 'My title is very cool' ); |
||
566 | $request->set_param( 'caption', 'This is a better caption.' ); |
||
567 | $request->set_param( 'description', 'Without a description, my attachment is descriptionless.' ); |
||
568 | $request->set_param( 'alt_text', 'Alt text is stored outside post schema.' ); |
||
569 | $response = $this->server->dispatch( $request ); |
||
570 | $data = $response->get_data(); |
||
571 | $attachment = get_post( $data['id'] ); |
||
572 | $this->assertEquals( 'My title is very cool', $data['title']['raw'] ); |
||
573 | $this->assertEquals( 'My title is very cool', $attachment->post_title ); |
||
574 | $this->assertEquals( 'This is a better caption.', $data['caption'] ); |
||
575 | $this->assertEquals( 'This is a better caption.', $attachment->post_excerpt ); |
||
576 | $this->assertEquals( 'Without a description, my attachment is descriptionless.', $data['description'] ); |
||
577 | $this->assertEquals( 'Without a description, my attachment is descriptionless.', $attachment->post_content ); |
||
578 | $this->assertEquals( 'Alt text is stored outside post schema.', $data['alt_text'] ); |
||
579 | $this->assertEquals( 'Alt text is stored outside post schema.', get_post_meta( $attachment->ID, '_wp_attachment_image_alt', true ) ); |
||
580 | } |
||
581 | |||
582 | public function test_update_item_parent() { |
||
602 | |||
603 | View Code Duplication | public function test_update_item_invalid_permissions() { |
|
604 | wp_set_current_user( $this->author_id ); |
||
605 | $attachment_id = $this->factory->attachment->create_object( $this->test_file, 0, array( |
||
606 | 'post_mime_type' => 'image/jpeg', |
||
607 | 'post_excerpt' => 'A sample caption', |
||
608 | 'post_author' => $this->editor_id, |
||
609 | ) ); |
||
610 | $request = new WP_REST_Request( 'POST', '/wp/v2/media/' . $attachment_id ); |
||
611 | $request->set_param( 'caption', 'This is a better caption.' ); |
||
612 | $response = $this->server->dispatch( $request ); |
||
613 | $this->assertErrorResponse( 'rest_cannot_edit', $response, 403 ); |
||
614 | } |
||
615 | |||
616 | public function test_update_item_invalid_post_type() { |
||
629 | |||
630 | View Code Duplication | public function test_delete_item() { |
|
631 | wp_set_current_user( $this->editor_id ); |
||
632 | $attachment_id = $this->factory->attachment->create_object( $this->test_file, 0, array( |
||
633 | 'post_mime_type' => 'image/jpeg', |
||
634 | 'post_excerpt' => 'A sample caption', |
||
635 | ) ); |
||
636 | $request = new WP_REST_Request( 'DELETE', '/wp/v2/media/' . $attachment_id ); |
||
637 | $request['force'] = true; |
||
638 | $response = $this->server->dispatch( $request ); |
||
639 | $this->assertEquals( 200, $response->get_status() ); |
||
640 | } |
||
641 | |||
642 | public function test_delete_item_no_trash() { |
||
658 | |||
659 | View Code Duplication | public function test_delete_item_invalid_delete_permissions() { |
|
670 | |||
671 | public function test_prepare_item() { |
||
672 | $attachment_id = $this->factory->attachment->create_object( $this->test_file, 0, array( |
||
673 | 'post_mime_type' => 'image/jpeg', |
||
674 | 'post_excerpt' => 'A sample caption', |
||
675 | 'post_author' => $this->editor_id, |
||
676 | ) ); |
||
677 | |||
678 | $attachment = get_post( $attachment_id ); |
||
679 | $request = new WP_REST_Request( 'GET', sprintf( '/wp/v2/media/%d', $attachment_id ) ); |
||
680 | $response = $this->server->dispatch( $request ); |
||
681 | $data = $response->get_data(); |
||
682 | $this->check_post_data( $attachment, $data, 'view', $response->get_links() ); |
||
683 | $this->check_post_data( $attachment, $data, 'embed', $response->get_links() ); |
||
684 | } |
||
685 | |||
686 | View Code Duplication | public function test_get_item_schema() { |
|
716 | |||
717 | public function test_get_additional_field_registration() { |
||
751 | |||
752 | public function test_additional_field_update_errors() { |
||
753 | $schema = array( |
||
754 | 'type' => 'integer', |
||
755 | 'description' => 'Some integer of mine', |
||
756 | 'enum' => array( 1, 2, 3, 4 ), |
||
757 | 'context' => array( 'view', 'edit' ), |
||
758 | ); |
||
759 | |||
760 | register_rest_field( 'attachment', 'my_custom_int', array( |
||
761 | 'schema' => $schema, |
||
762 | 'get_callback' => array( $this, 'additional_field_get_callback' ), |
||
763 | 'update_callback' => array( $this, 'additional_field_update_callback' ), |
||
764 | ) ); |
||
765 | |||
785 | |||
786 | public function additional_field_get_callback( $object, $request ) { |
||
789 | |||
790 | public function additional_field_update_callback( $value, $attachment ) { |
||
795 | |||
796 | public function tearDown() { |
||
805 | |||
806 | protected function check_post_data( $attachment, $data, $context = 'view', $links ) { |
||
823 | |||
824 | } |
||
825 |
This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.
Both the
$myVar
assignment in line 1 and the$higher
assignment in line 2 are dead. The first because$myVar
is never used and the second because$higher
is always overwritten for every possible time line.