WP_Test_REST_Post_Type_Controller_Testcase   B
last analyzed

Complexity

Total Complexity 49

Size/Duplication

Total Lines 311
Duplicated Lines 24.12 %

Coupling/Cohesion

Components 1
Dependencies 1

Importance

Changes 0
Metric Value
dl 75
loc 311
rs 8.5454
c 0
b 0
f 0
wmc 49
lcom 1
cbo 1

8 Methods

Rating   Name   Duplication   Size   Complexity  
F check_post_data() 51 202 39
B check_get_posts_response() 0 26 4
A check_get_post_response() 0 10 1
A check_create_post_response() 12 12 1
A check_update_post_response() 12 12 1
A set_post_data() 0 13 1
A set_raw_post_data() 0 13 1
A protected_title_format() 0 3 1

How to fix   Duplicated Code    Complexity   

Duplicated Code

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 Class

 Tip:   Before tackling complexity, make sure that you eliminate any duplication first. This often can reduce the size of classes significantly.

Complex classes like WP_Test_REST_Post_Type_Controller_Testcase 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_Post_Type_Controller_Testcase, and based on these observations, apply Extract Interface, too.

1
<?php
2
3
abstract class WP_Test_REST_Post_Type_Controller_Testcase extends WP_Test_REST_Controller_Testcase {
4
5
	protected function check_post_data( $post, $data, $context, $links ) {
6
		$post_type_obj = get_post_type_object( $post->post_type );
7
8
		// Standard fields
9
		$this->assertEquals( $post->ID, $data['id'] );
10
		$this->assertEquals( $post->post_name, $data['slug'] );
11
		$this->assertEquals( get_permalink( $post->ID ), $data['link'] );
12
		if ( '0000-00-00 00:00:00' === $post->post_date_gmt ) {
13
			$this->assertNull( $data['date_gmt'] );
14
		}
15
		$this->assertEquals( mysql_to_rfc3339( $post->post_date ), $data['date'] );
16
17
		if ( '0000-00-00 00:00:00' === $post->post_modified_gmt ) {
18
			$this->assertNull( $data['modified_gmt'] );
19
		}
20
		$this->assertEquals( mysql_to_rfc3339( $post->post_modified ), $data['modified'] );
21
22
		// author
23
		if ( post_type_supports( $post->post_type, 'author' ) ) {
24
			$this->assertEquals( $post->post_author, $data['author'] );
25
		} else {
26
			$this->assertEmpty( $data['author'] );
27
		}
28
29
		// post_parent
30
		if ( $post_type_obj->hierarchical ) {
31
			$this->assertArrayHasKey( 'parent', $data );
32
			if ( $post->post_parent ) {
33
				if ( is_int( $data['parent'] ) ) {
34
					$this->assertEquals( $post->post_parent, $data['parent'] );
35
				} else {
36
					$this->assertEquals( $post->post_parent, $data['parent']['id'] );
37
					$this->check_get_post_response( $data['parent'], get_post( $data['parent']['id'] ), 'view-parent' );
38
				}
39
			} else {
40
				$this->assertEmpty( $data['parent'] );
41
			}
42
		} else {
43
			$this->assertFalse( isset( $data['parent'] ) );
44
		}
45
46
		// page attributes
47 View Code Duplication
		if ( $post_type_obj->hierarchical && post_type_supports( $post->post_type, 'page-attributes' ) ) {
48
			$this->assertEquals( $post->menu_order, $data['menu_order'] );
49
		} else {
50
			$this->assertFalse( isset( $data['menu_order'] ) );
51
		}
52
53
		// Comments
54
		if ( post_type_supports( $post->post_type, 'comments' ) ) {
55
			$this->assertEquals( $post->comment_status, $data['comment_status'] );
56
			$this->assertEquals( $post->ping_status, $data['ping_status'] );
57
		} else {
58
			$this->assertFalse( isset( $data['comment_status'] ) );
59
			$this->assertFalse( isset( $data['ping_status'] ) );
60
		}
61
62
		if ( 'post' === $post->post_type ) {
63
			$this->assertEquals( is_sticky( $post->ID ), $data['sticky'] );
64
		}
65
66
		if ( 'post' === $post->post_type && 'edit' === $context ) {
67
			$this->assertEquals( $post->post_password, $data['password'] );
68
		}
69
70
		if ( 'page' === $post->post_type ) {
71
			$this->assertEquals( get_page_template_slug( $post->ID ), $data['template'] );
72
		}
73
74 View Code Duplication
		if ( post_type_supports( $post->post_type, 'thumbnail' ) ) {
75
			$this->assertEquals( (int) get_post_thumbnail_id( $post->ID ), $data['featured_media'] );
76
		} else {
77
			$this->assertFalse( isset( $data['featured_media'] ) );
78
		}
79
80
		// Check post format.
81
		if ( post_type_supports( $post->post_type, 'post-formats' ) ) {
82
			$post_format = get_post_format( $post->ID );
83
			if ( empty( $post_format ) ) {
84
				$this->assertEquals( 'standard', $data['format'] );
85
			} else {
86
				$this->assertEquals( get_post_format( $post->ID ), $data['format'] );
87
			}
88
		} else {
89
			$this->assertFalse( isset( $data['format'] ) );
90
		}
91
92
		// Check filtered values.
93
		if ( post_type_supports( $post->post_type, 'title' ) ) {
94
			add_filter( 'protected_title_format', array( $this, 'protected_title_format' ) );
95
			$this->assertEquals( get_the_title( $post->ID ), $data['title']['rendered'] );
96
			remove_filter( 'protected_title_format', array( $this, 'protected_title_format' ) );
97
			if ( 'edit' === $context ) {
98
				$this->assertEquals( $post->post_title, $data['title']['raw'] );
99
			} else {
100
				$this->assertFalse( isset( $data['title']['raw'] ) );
101
			}
102
		} else {
103
			$this->assertFalse( isset( $data['title'] ) );
104
		}
105
106 View Code Duplication
		if ( post_type_supports( $post->post_type, 'editor' ) ) {
107
			// TODO: apply content filter for more accurate testing.
108
			if ( ! $post->post_password ) {
109
				$this->assertEquals( wpautop( $post->post_content ), $data['content']['rendered'] );
110
			}
111
112
			if ( 'edit' === $context ) {
113
				$this->assertEquals( $post->post_content, $data['content']['raw'] );
114
			} else {
115
				$this->assertFalse( isset( $data['content']['raw'] ) );
116
			}
117
		} else {
118
			$this->assertFalse( isset( $data['content'] ) );
119
		}
120
121 View Code Duplication
		if ( post_type_supports( $post->post_type, 'excerpt' ) ) {
122
			if ( empty( $post->post_password ) ) {
123
				// TODO: apply excerpt filter for more accurate testing.
124
				$this->assertEquals( wpautop( $post->post_excerpt ), $data['excerpt']['rendered'] );
125
			} else {
126
				// TODO: better testing for excerpts for password protected posts.
127
			}
128
			if ( 'edit' === $context ) {
129
				$this->assertEquals( $post->post_excerpt, $data['excerpt']['raw'] );
130
			} else {
131
				$this->assertFalse( isset( $data['excerpt']['raw'] ) );
132
			}
133
		} else {
134
			$this->assertFalse( isset( $data['excerpt'] ) );
135
		}
136
137
		$this->assertEquals( $post->guid, $data['guid']['rendered'] );
138
139
		if ( 'edit' === $context ) {
140
			$this->assertEquals( $post->guid, $data['guid']['raw'] );
141
			$this->assertEquals( $post->post_status, $data['status'] );
142
143
			if ( '0000-00-00 00:00:00' === $post->post_date_gmt ) {
144
				$this->assertNull( $data['date_gmt'] );
145
			} else {
146
				$this->assertEquals( mysql_to_rfc3339( $post->post_date_gmt ), $data['date_gmt'] );
147
			}
148
149
			if ( '0000-00-00 00:00:00' === $post->post_modified_gmt ) {
150
				$this->assertNull( $data['modified_gmt'] );
151
			} else {
152
				$this->assertEquals( mysql_to_rfc3339( $post->post_modified_gmt ), $data['modified_gmt'] );
153
			}
154
		}
155
156
		$taxonomies = wp_list_filter( get_object_taxonomies( $post->post_type, 'objects' ), array( 'show_in_rest' => true ) );
157
		foreach ( $taxonomies as $taxonomy ) {
158
			$this->assertTrue( isset( $data[ $taxonomy->rest_base ] ) );
159
			$terms = wp_get_object_terms( $post->ID, $taxonomy->name, array( 'fields' => 'ids' ) );
160
			sort( $terms );
161
			sort( $data[ $taxonomy->rest_base ] );
162
			$this->assertEquals( $terms, $data[ $taxonomy->rest_base ] );
163
		}
164
165
		// test links
166
		if ( $links ) {
167
168
			$links = test_rest_expand_compact_links( $links );
169
			$post_type = get_post_type_object( $data['type'] );
170
			$this->assertEquals( $links['self'][0]['href'], rest_url( 'wp/v2/' . $post_type->rest_base . '/' . $data['id'] ) );
171
			$this->assertEquals( $links['collection'][0]['href'], rest_url( 'wp/v2/' . $post_type->rest_base ) );
172
			$this->assertEquals( $links['about'][0]['href'], rest_url( 'wp/v2/types/' . $data['type'] ) );
173
174 View Code Duplication
			if ( post_type_supports( $post->post_type, 'author' ) && $data['author'] ) {
175
				$this->assertEquals( $links['author'][0]['href'], rest_url( 'wp/v2/users/' . $data['author'] ) );
176
			}
177
178 View Code Duplication
			if ( post_type_supports( $post->post_type, 'comments' ) ) {
179
				$this->assertEquals( $links['replies'][0]['href'], add_query_arg( 'post', $data['id'], rest_url( 'wp/v2/comments' ) ) );
180
			}
181
182 View Code Duplication
			if ( post_type_supports( $post->post_type, 'revisions' ) ) {
183
				$this->assertEquals( $links['version-history'][0]['href'], rest_url( 'wp/v2/' . $post_type->rest_base . '/' . $data['id'] . '/revisions' ) );
184
			}
185
186 View Code Duplication
			if ( $post_type->hierarchical && ! empty( $data['parent'] ) ) {
187
				$this->assertEquals( $links['up'][0]['href'], rest_url( 'wp/v2/' . $post_type->rest_base . '/' . $data['parent'] ) );
188
			}
189
190
			if ( ! in_array( $data['type'], array( 'attachment', 'nav_menu_item', 'revision' ) ) ) {
191
				$this->assertEquals( $links['https://api.w.org/attachment'][0]['href'], add_query_arg( 'parent', $data['id'], rest_url( 'wp/v2/media' ) ) );
192
			}
193
194
			if ( ! empty( $data['featured_media'] ) ) {
195
				$this->assertEquals( $links['https://api.w.org/featuredmedia'][0]['href'], rest_url( 'wp/v2/media/' . $data['featured_media'] ) );
196
			}
197
198
			$num = 0;
199
			foreach ( $taxonomies as $key => $taxonomy ) {
200
				$this->assertEquals( $taxonomy->name, $links['https://api.w.org/term'][ $num ]['attributes']['taxonomy'] );
201
				$this->assertEquals( add_query_arg( 'post', $data['id'], rest_url( 'wp/v2/' . $taxonomy->rest_base ) ), $links['https://api.w.org/term'][ $num ]['href'] );
202
				$num++;
203
			}
204
		}
205
206
	}
207
208
	protected function check_get_posts_response( $response, $context = 'view' ) {
209
		$this->assertNotInstanceOf( 'WP_Error', $response );
210
		$response = rest_ensure_response( $response );
211
		$this->assertEquals( 200, $response->get_status() );
212
213
		$headers = $response->get_headers();
214
		$this->assertArrayHasKey( 'X-WP-Total', $headers );
215
		$this->assertArrayHasKey( 'X-WP-TotalPages', $headers );
216
217
		$all_data = $response->get_data();
218
		foreach ( $all_data as $data ) {
219
			$post = get_post( $data['id'] );
220
			// as the links for the post are "response_links" format in the data array we have to pull them
221
			// out and parse them.
222
			$links = $data['_links'];
223
			foreach ( $links as &$links_array ) {
224
				foreach ( $links_array as &$link ) {
225
					$attributes = array_diff_key( $link, array( 'href' => 1, 'name' => 1 ) );
226
					$link = array_diff_key( $link, $attributes );
227
					$link['attributes'] = $attributes;
228
				}
229
			}
230
231
			$this->check_post_data( $post, $data, $context, $links );
232
		}
233
	}
234
235
	protected function check_get_post_response( $response, $context = 'view' ) {
236
		$this->assertNotInstanceOf( 'WP_Error', $response );
237
		$response = rest_ensure_response( $response );
238
		$this->assertEquals( 200, $response->get_status() );
239
240
		$data = $response->get_data();
241
		$post = get_post( $data['id'] );
242
		$this->check_post_data( $post, $data, $context, $response->get_links() );
243
244
	}
245
246 View Code Duplication
	protected function check_create_post_response( $response ) {
247
		$this->assertNotInstanceOf( 'WP_Error', $response );
248
		$response = rest_ensure_response( $response );
249
250
		$this->assertEquals( 201, $response->get_status() );
251
		$headers = $response->get_headers();
252
		$this->assertArrayHasKey( 'Location', $headers );
253
254
		$data = $response->get_data();
255
		$post = get_post( $data['id'] );
256
		$this->check_post_data( $post, $data, 'edit', $response->get_links() );
257
	}
258
259 View Code Duplication
	protected function check_update_post_response( $response ) {
260
		$this->assertNotInstanceOf( 'WP_Error', $response );
261
		$response = rest_ensure_response( $response );
262
263
		$this->assertEquals( 200, $response->get_status() );
264
		$headers = $response->get_headers();
265
		$this->assertArrayNotHasKey( 'Location', $headers );
266
267
		$data = $response->get_data();
268
		$post = get_post( $data['id'] );
269
		$this->check_post_data( $post, $data, 'edit', $response->get_links() );
270
	}
271
272
	protected function set_post_data( $args = array() ) {
273
		$defaults = array(
274
			'title'   => rand_str(),
275
			'content' => rand_str(),
276
			'excerpt' => rand_str(),
277
			'name'    => 'test',
278
			'status'  => 'publish',
279
			'author'  => get_current_user_id(),
280
			'type'    => 'post',
281
		);
282
283
		return wp_parse_args( $args, $defaults );
284
	}
285
286
	protected function set_raw_post_data( $args = array() ) {
287
		return wp_parse_args( $args, $this->set_post_data( array(
288
			'title'   => array(
289
				'raw' => rand_str(),
290
			),
291
			'content' => array(
292
				'raw' => rand_str(),
293
			),
294
			'excerpt' => array(
295
				'raw' => rand_str(),
296
			),
297
		) ) );
298
	}
299
300
	/**
301
	 * Overwrite the default protected title format.
302
	 *
303
	 * By default WordPress will show password protected posts with a title of
304
	 * "Protected: %s", as the REST API communicates the protected status of a post
305
	 * in a machine readable format, we remove the "Protected: " prefix.
306
	 *
307
	 * @param  string $format
0 ignored issues
show
Bug introduced by
There is no parameter named $format. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
308
	 * @return string
309
	 */
310
	public function protected_title_format() {
311
		return '%s';
312
	}
313
}
314