Issues (90)

Security Analysis    no request data  

This project does not seem to handle request data directly as such no vulnerable execution paths were found.

  Cross-Site Scripting
Cross-Site Scripting enables an attacker to inject code into the response of a web-request that is viewed by other users. It can for example be used to bypass access controls, or even to take over other users' accounts.
  File Exposure
File Exposure allows an attacker to gain access to local files that he should not be able to access. These files can for example include database credentials, or other configuration files.
  File Manipulation
File Manipulation enables an attacker to write custom data to files. This potentially leads to injection of arbitrary code on the server.
  Object Injection
Object Injection enables an attacker to inject an object into PHP code, and can lead to arbitrary code execution, file exposure, or file manipulation attacks.
  Code Injection
Code Injection enables an attacker to execute arbitrary code on the server.
  Response Splitting
Response Splitting can be used to send arbitrary responses.
  File Inclusion
File Inclusion enables an attacker to inject custom files into PHP's file loading mechanism, either explicitly passed to include, or for example via PHP's auto-loading mechanism.
  Command Injection
Command Injection enables an attacker to inject a shell command that is execute with the privileges of the web-server. This can be used to expose sensitive data, or gain access of your server.
  SQL Injection
SQL Injection enables an attacker to execute arbitrary SQL code on your database server gaining access to user data, or manipulating user data.
  XPath Injection
XPath Injection enables an attacker to modify the parts of XML document that are read. If that XML document is for example used for authentication, this can lead to further vulnerabilities similar to SQL Injection.
  LDAP Injection
LDAP Injection enables an attacker to inject LDAP statements potentially granting permission to run unauthorized queries, or modify content inside the LDAP tree.
  Header Injection
  Other Vulnerability
This category comprises other attack vectors such as manipulating the PHP runtime, loading custom extensions, freezing the runtime, or similar.
  Regex Injection
Regex Injection enables an attacker to execute arbitrary code in your PHP process.
  XML Injection
XML Injection enables an attacker to read files on your local filesystem including configuration files, or can be abused to freeze your web-server process.
  Variable Injection
Variable Injection enables an attacker to overwrite program variables with custom data, and can lead to further vulnerabilities.
Unfortunately, the security analysis is currently not available for your project. If you are a non-commercial open-source project, please contact support to gain access.

tests/test-rest-attachments-controller.php (3 issues)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
3
/**
4
 * Unit tests covering WP_REST_Attachments_Controller functionality
5
 *
6
 * @package WordPress
7
 * @subpackage JSON API
8
 */
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() {
34
		$routes = $this->server->get_routes();
35
		$this->assertArrayHasKey( '/wp/v2/media', $routes );
36
		$this->assertCount( 2, $routes['/wp/v2/media'] );
37
		$this->assertArrayHasKey( '/wp/v2/media/(?P<id>[\d]+)', $routes );
38
		$this->assertCount( 3, $routes['/wp/v2/media/(?P<id>[\d]+)'] );
39
	}
40
41
	public static function disposition_provider() {
42
		return array(
43
			// Types
44
			array( 'attachment; filename="foo.jpg"', 'foo.jpg' ),
45
			array( 'inline; filename="foo.jpg"', 'foo.jpg' ),
46
			array( 'form-data; filename="foo.jpg"', 'foo.jpg' ),
47
48
			// Formatting
49
			array( 'attachment; filename="foo.jpg"', 'foo.jpg' ),
50
			array( 'attachment; filename=foo.jpg', 'foo.jpg' ),
51
			array( 'attachment;filename="foo.jpg"', 'foo.jpg' ),
52
			array( 'attachment;filename=foo.jpg', 'foo.jpg' ),
53
			array( 'attachment; filename = "foo.jpg"', 'foo.jpg' ),
54
			array( 'attachment; filename = foo.jpg', 'foo.jpg' ),
55
			array( "attachment;\tfilename\t=\t\"foo.jpg\"", 'foo.jpg' ),
56
			array( "attachment;\tfilename\t=\tfoo.jpg", 'foo.jpg' ),
57
			array( 'attachment; filename = my foo picture.jpg', 'my foo picture.jpg' ),
58
59
			// Extensions
60
			array( 'form-data; name="myfile"; filename="foo.jpg"', 'foo.jpg' ),
61
			array( 'form-data; name="myfile"; filename="foo.jpg"; something="else"', 'foo.jpg' ),
62
			array( 'form-data; name=myfile; filename=foo.jpg; something=else', 'foo.jpg' ),
63
			array( 'form-data; name=myfile; filename=my foo.jpg; something=else', 'my foo.jpg' ),
64
65
			// Invalid
66
			array( 'filename="foo.jpg"', null ),
67
			array( 'filename-foo.jpg', null ),
68
			array( 'foo.jpg', null ),
69
			array( 'unknown; notfilename="foo.jpg"', null ),
70
		);
71
	}
72
73
	/**
74
	 * @dataProvider disposition_provider
75
	 */
76
	public function test_parse_disposition( $header, $expected ) {
77
		$header_list = array( $header );
78
		$parsed = WP_REST_Attachments_Controller::get_filename_from_disposition( $header_list );
79
		$this->assertEquals( $expected, $parsed );
80
	}
81
82
	public function test_context_param() {
83
		// Collection
84
		$request = new WP_REST_Request( 'OPTIONS', '/wp/v2/media' );
85
		$response = $this->server->dispatch( $request );
86
		$data = $response->get_data();
87
		$this->assertEquals( 'view', $data['endpoints'][0]['args']['context']['default'] );
88
		$this->assertEquals( array( 'view', 'embed', 'edit' ), $data['endpoints'][0]['args']['context']['enum'] );
89
		// Single
90
		$attachment_id = $this->factory->attachment->create_object( $this->test_file, 0, array(
91
			'post_mime_type' => 'image/jpeg',
92
			'post_excerpt'   => 'A sample caption',
93
		) );
94
		$request = new WP_REST_Request( 'OPTIONS', '/wp/v2/media/' . $attachment_id );
95
		$response = $this->server->dispatch( $request );
96
		$data = $response->get_data();
97
		$this->assertEquals( 'view', $data['endpoints'][0]['args']['context']['default'] );
98
		$this->assertEquals( array( 'view', 'embed', 'edit' ), $data['endpoints'][0]['args']['context']['enum'] );
99
	}
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() {
142
		wp_set_current_user( 0 );
143
		$id1 = $this->factory->attachment->create_object( $this->test_file, 0, array(
144
			'post_mime_type' => 'image/jpeg',
145
			'post_excerpt'   => 'A sample caption',
146
		) );
147
		$draft_post = $this->factory->post->create( array( 'post_status' => 'draft' ) );
148
		$id2 = $this->factory->attachment->create_object( $this->test_file, $draft_post, array(
149
			'post_mime_type' => 'image/jpeg',
150
			'post_excerpt'   => 'A sample caption',
151
		) );
152
		$published_post = $this->factory->post->create( array( 'post_status' => 'publish' ) );
153
		$id3 = $this->factory->attachment->create_object( $this->test_file, $published_post, array(
154
			'post_mime_type' => 'image/jpeg',
155
			'post_excerpt'   => 'A sample caption',
156
		) );
157
		$request = new WP_REST_Request( 'GET', '/wp/v2/media' );
158
		$response = $this->server->dispatch( $request );
159
		$data = $response->get_data();
160
		$this->assertCount( 2, $data );
161
		$ids = wp_list_pluck( $data, 'id' );
162
		$this->assertTrue( in_array( $id1, $ids ) );
163
		$this->assertFalse( in_array( $id2, $ids ) );
164
		$this->assertTrue( in_array( $id3, $ids ) );
165
166
		$this->check_get_posts_response( $response );
167
	}
168
169 View Code Duplication
	public function test_get_items_logged_in_editor() {
170
		wp_set_current_user( $this->editor_id );
171
		$id1 = $this->factory->attachment->create_object( $this->test_file, 0, array(
172
			'post_mime_type' => 'image/jpeg',
173
			'post_excerpt'   => 'A sample caption',
174
		) );
175
		$draft_post = $this->factory->post->create( array( 'post_status' => 'draft' ) );
176
		$id2 = $this->factory->attachment->create_object( $this->test_file, $draft_post, array(
177
			'post_mime_type' => 'image/jpeg',
178
			'post_excerpt'   => 'A sample caption',
179
		) );
180
		$published_post = $this->factory->post->create( array( 'post_status' => 'publish' ) );
181
		$id3 = $this->factory->attachment->create_object( $this->test_file, $published_post, array(
182
			'post_mime_type' => 'image/jpeg',
183
			'post_excerpt'   => 'A sample caption',
184
		) );
185
		$request = new WP_REST_Request( 'GET', '/wp/v2/media' );
186
		$response = $this->server->dispatch( $request );
187
188
		$data = $response->get_data();
189
		$this->assertCount( 3, $data );
190
		$ids = wp_list_pluck( $data, 'id' );
191
		$this->assertTrue( in_array( $id1, $ids ) );
192
		$this->assertTrue( in_array( $id2, $ids ) );
193
		$this->assertTrue( in_array( $id3, $ids ) );
194
	}
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() {
286
		// Logged out users can't make the request
287
		wp_set_current_user( 0 );
288
		$attachment_id1 = $this->factory->attachment->create_object( $this->test_file, 0, array(
289
			'post_mime_type' => 'image/jpeg',
290
			'post_excerpt'   => 'A sample caption',
291
			'post_status'    => 'private',
292
		) );
293
		$request = new WP_REST_Request( 'GET', '/wp/v2/media' );
294
		$request->set_param( 'status', 'private' );
295
		$response = $this->server->dispatch( $request );
296
		$this->assertErrorResponse( 'rest_invalid_param', $response, 400 );
297
		// Properly authorized users can make the request
298
		wp_set_current_user( $this->editor_id );
299
		$response = $this->server->dispatch( $request );
300
		$this->assertEquals( 200, $response->get_status() );
301
		$data = $response->get_data();
302
		$this->assertEquals( $attachment_id1, $data[0]['id'] );
303
	}
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(
0 ignored issues
show
$id1 is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

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.

Loading history...
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(
0 ignored issues
show
$id3 is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

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.

Loading history...
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() {
352
		$attachment_id = $this->factory->attachment->create_object( $this->test_file, 0, array(
353
			'post_mime_type' => 'image/jpeg',
354
			'post_excerpt'   => 'A sample caption',
355
		), $this->test_file );
356
357
		add_image_size( 'rest-api-test', 119, 119, true );
358
		wp_update_attachment_metadata( $attachment_id, wp_generate_attachment_metadata( $attachment_id, $this->test_file ) );
359
360
		$request = new WP_REST_Request( 'GET', '/wp/v2/media/' . $attachment_id );
361
		$response = $this->server->dispatch( $request );
362
		$data = $response->get_data();
363
		$image_src = wp_get_attachment_image_src( $attachment_id, 'rest-api-test' );
364
		$original_image_src = wp_get_attachment_image_src( $attachment_id, 'full' );
365
		remove_image_size( 'rest-api-test' );
366
367
		$this->assertEquals( $image_src[0], $data['media_details']['sizes']['rest-api-test']['source_url'] );
368
		$this->assertEquals( 'image/jpeg', $data['media_details']['sizes']['rest-api-test']['mime_type'] );
369
		$this->assertEquals( $original_image_src[0], $data['media_details']['sizes']['full']['source_url'] );
370
		$this->assertEquals( 'image/jpeg', $data['media_details']['sizes']['full']['mime_type'] );
371
	}
372
373
	public function test_get_item_sizes_with_no_url() {
374
		$attachment_id = $this->factory->attachment->create_object( $this->test_file, 0, array(
375
			'post_mime_type' => 'image/jpeg',
376
			'post_excerpt'   => 'A sample caption',
377
		), $this->test_file );
378
379
		add_image_size( 'rest-api-test', 119, 119, true );
380
		wp_update_attachment_metadata( $attachment_id, wp_generate_attachment_metadata( $attachment_id, $this->test_file ) );
381
382
		add_filter( 'wp_get_attachment_image_src', '__return_false' );
383
384
		$request = new WP_REST_Request( 'GET', '/wp/v2/media/' . $attachment_id );
385
		$response = $this->server->dispatch( $request );
386
		$data = $response->get_data();
387
		remove_filter( 'wp_get_attachment_image_src', '__return_false' );
388
		remove_image_size( 'rest-api-test' );
389
390
		$this->assertFalse( isset( $data['media_details']['sizes']['rest-api-test']['source_url'] ) );
391
	}
392
393 View Code Duplication
	public function test_get_item_private_post() {
394
		wp_set_current_user( 0 );
395
		$draft_post = $this->factory->post->create( array( 'post_status' => 'draft' ) );
396
		$id1 = $this->factory->attachment->create_object( $this->test_file, $draft_post, array(
397
			'post_mime_type' => 'image/jpeg',
398
			'post_excerpt'   => 'A sample caption',
399
		) );
400
		$request = new WP_REST_Request( 'GET', '/wp/v2/media/' . $id1 );
401
		$response = $this->server->dispatch( $request );
402
		$this->assertEquals( 403, $response->get_status() );
403
	}
404
405
	public function test_create_item() {
406
		wp_set_current_user( $this->author_id );
407
		$request = new WP_REST_Request( 'POST', '/wp/v2/media' );
408
		$request->set_header( 'Content-Type', 'image/jpeg' );
409
		$request->set_header( 'Content-Disposition', 'attachment; filename=canola.jpg' );
410
		$request->set_body( file_get_contents( $this->test_file ) );
411
		$response = $this->server->dispatch( $request );
412
		$data = $response->get_data();
413
		$this->assertEquals( 201, $response->get_status() );
414
		$this->assertEquals( 'image', $data['media_type'] );
415
		$this->assertEquals( 'A field of amazing canola', $data['title']['rendered'] );
416
		$this->assertEquals( 'The description for the image', $data['caption'] );
417
	}
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() {
438
		wp_set_current_user( $this->author_id );
439
		$request = new WP_REST_Request( 'POST', '/wp/v2/media' );
440
		$request->set_file_params( array(
441
			'file' => array(
442
				'file'     => file_get_contents( $this->test_file ),
443
				'name'     => 'canola.jpg',
444
				'size'     => filesize( $this->test_file ),
445
				'tmp_name' => $this->test_file,
446
			),
447
		) );
448
		$request->set_header( 'Content-MD5', md5_file( $this->test_file ) );
449
		$response = $this->server->dispatch( $request );
450
		$this->assertEquals( 201, $response->get_status() );
451
	}
452
453
	public function test_create_item_empty_body() {
454
		wp_set_current_user( $this->author_id );
455
		$request = new WP_REST_Request( 'POST', '/wp/v2/media' );
456
		$response = $this->server->dispatch( $request );
457
		$this->assertErrorResponse( 'rest_upload_no_data', $response, 400 );
458
	}
459
460
	public function test_create_item_missing_content_type() {
461
		wp_set_current_user( $this->author_id );
462
		$request = new WP_REST_Request( 'POST', '/wp/v2/media' );
463
		$request->set_body( file_get_contents( $this->test_file ) );
464
		$response = $this->server->dispatch( $request );
465
		$this->assertErrorResponse( 'rest_upload_no_content_type', $response, 400 );
466
	}
467
468
	public function test_create_item_missing_content_disposition() {
469
		wp_set_current_user( $this->author_id );
470
		$request = new WP_REST_Request( 'POST', '/wp/v2/media' );
471
		$request->set_header( 'Content-Type', 'image/jpeg' );
472
		$request->set_body( file_get_contents( $this->test_file ) );
473
		$response = $this->server->dispatch( $request );
474
		$this->assertErrorResponse( 'rest_upload_no_content_disposition', $response, 400 );
475
	}
476
477 View Code Duplication
	public function test_create_item_bad_md5_header() {
478
		wp_set_current_user( $this->author_id );
479
		$request = new WP_REST_Request( 'POST', '/wp/v2/media' );
480
		$request->set_header( 'Content-Type', 'image/jpeg' );
481
		$request->set_header( 'Content-Disposition', 'attachment; filename=canola.jpg' );
482
		$request->set_header( 'Content-MD5', 'abc123' );
483
		$request->set_body( file_get_contents( $this->test_file ) );
484
		$response = $this->server->dispatch( $request );
485
		$this->assertErrorResponse( 'rest_upload_hash_mismatch', $response, 412 );
486
	}
487
488 View Code Duplication
	public function test_create_item_with_files_bad_md5_header() {
489
		wp_set_current_user( $this->author_id );
490
		$request = new WP_REST_Request( 'POST', '/wp/v2/media' );
491
		$request->set_file_params( array(
492
			'file' => array(
493
				'file'     => file_get_contents( $this->test_file ),
494
				'name'     => 'canola.jpg',
495
				'size'     => filesize( $this->test_file ),
496
				'tmp_name' => $this->test_file,
497
			),
498
		) );
499
		$request->set_header( 'Content-MD5', 'abc123' );
500
		$response = $this->server->dispatch( $request );
501
		$this->assertErrorResponse( 'rest_upload_hash_mismatch', $response, 412 );
502
	}
503
504
	public function test_create_item_invalid_upload_files_capability() {
505
		wp_set_current_user( $this->contributor_id );
506
		$request = new WP_REST_Request( 'POST', '/wp/v2/media' );
507
		$response = $this->server->dispatch( $request );
508
		$this->assertErrorResponse( 'rest_cannot_create', $response, 403 );
509
	}
510
511
	public function test_create_item_invalid_edit_permissions() {
512
		$post_id = $this->factory->post->create( array( 'post_author' => $this->editor_id ) );
513
		wp_set_current_user( $this->author_id );
514
		$request = new WP_REST_Request( 'POST', '/wp/v2/media' );
515
		$request->set_param( 'post', $post_id );
516
		$response = $this->server->dispatch( $request );
517
		$this->assertErrorResponse( 'rest_cannot_edit', $response, 403 );
518
	}
519
520 View Code Duplication
	public function test_create_item_invalid_post_type() {
521
		$attachment_id = $this->factory->post->create( array( 'post_type' => 'attachment', 'post_status' => 'inherit', 'post_parent' => 0 ) );
522
		wp_set_current_user( $this->editor_id );
523
		$request = new WP_REST_Request( 'POST', '/wp/v2/media' );
524
		$request->set_header( 'Content-Type', 'image/jpeg' );
525
		$request->set_header( 'Content-Disposition', 'attachment; filename=canola.jpg' );
526
		$request->set_body( file_get_contents( $this->test_file ) );
527
		$request->set_param( 'post', $attachment_id );
528
		$response = $this->server->dispatch( $request );
529
		$this->assertErrorResponse( 'rest_invalid_param', $response, 400 );
530
	}
531
532 View Code Duplication
	public function test_create_item_alt_text() {
533
		wp_set_current_user( $this->author_id );
534
		$request = new WP_REST_Request( 'POST', '/wp/v2/media' );
535
		$request->set_header( 'Content-Type', 'image/jpeg' );
536
		$request->set_header( 'Content-Disposition', 'attachment; filename=canola.jpg' );
537
538
		$request->set_body( file_get_contents( $this->test_file ) );
539
		$request->set_param( 'alt_text', 'test alt text' );
540
		$response = $this->server->dispatch( $request );
541
		$attachment = $response->get_data();
542
		$this->assertEquals( 'test alt text', $attachment['alt_text'] );
543
	}
544
545 View Code Duplication
	public function test_create_item_unsafe_alt_text() {
546
		wp_set_current_user( $this->author_id );
547
		$request = new WP_REST_Request( 'POST', '/wp/v2/media' );
548
		$request->set_header( 'Content-Type', 'image/jpeg' );
549
		$request->set_header( 'Content-Disposition', 'attachment; filename=canola.jpg' );
550
		$request->set_body( file_get_contents( $this->test_file ) );
551
		$request->set_param( 'alt_text', '<script>alert(document.cookie)</script>' );
552
		$response = $this->server->dispatch( $request );
553
		$attachment = $response->get_data();
554
		$this->assertEquals( '', $attachment['alt_text'] );
555
	}
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() {
583
		wp_set_current_user( $this->editor_id );
584
		$original_parent = $this->factory->post->create( array() );
585
		$attachment_id = $this->factory->attachment->create_object( $this->test_file, $original_parent, array(
586
			'post_mime_type' => 'image/jpeg',
587
			'post_excerpt'   => 'A sample caption',
588
			'post_author'    => $this->editor_id,
589
		) );
590
591
		$attachment = get_post( $attachment_id );
592
		$this->assertEquals( $original_parent, $attachment->post_parent );
593
594
		$new_parent = $this->factory->post->create( array() );
595
		$request = new WP_REST_Request( 'POST', '/wp/v2/media/' . $attachment_id );
596
		$request->set_param( 'post', $new_parent );
597
		$this->server->dispatch( $request );
598
599
		$attachment = get_post( $attachment_id );
600
		$this->assertEquals( $new_parent, $attachment->post_parent );
601
	}
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() {
617
		$attachment_id = $this->factory->post->create( array( 'post_type' => 'attachment', 'post_status' => 'inherit', 'post_parent' => 0 ) );
0 ignored issues
show
$attachment_id is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

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.

Loading history...
618
		wp_set_current_user( $this->editor_id );
619
		$attachment_id = $this->factory->attachment->create_object( $this->test_file, 0, array(
620
			'post_mime_type' => 'image/jpeg',
621
			'post_excerpt'   => 'A sample caption',
622
			'post_author'    => $this->editor_id,
623
		) );
624
		$request = new WP_REST_Request( 'POST', '/wp/v2/media/' . $attachment_id );
625
		$request->set_param( 'post', $attachment_id );
626
		$response = $this->server->dispatch( $request );
627
		$this->assertErrorResponse( 'rest_invalid_param', $response, 400 );
628
	}
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() {
643
		wp_set_current_user( $this->editor_id );
644
		$attachment_id = $this->factory->attachment->create_object( $this->test_file, 0, array(
645
			'post_mime_type' => 'image/jpeg',
646
			'post_excerpt'   => 'A sample caption',
647
		) );
648
649
		// Attempt trashing
650
		$request = new WP_REST_Request( 'DELETE', '/wp/v2/media/' . $attachment_id );
651
		$response = $this->server->dispatch( $request );
652
		$this->assertErrorResponse( 'rest_trash_not_supported', $response, 501 );
653
654
		// Ensure the post still exists
655
		$post = get_post( $attachment_id );
656
		$this->assertNotEmpty( $post );
657
	}
658
659 View Code Duplication
	public function test_delete_item_invalid_delete_permissions() {
660
		wp_set_current_user( $this->author_id );
661
		$attachment_id = $this->factory->attachment->create_object( $this->test_file, 0, array(
662
			'post_mime_type' => 'image/jpeg',
663
			'post_excerpt'   => 'A sample caption',
664
			'post_author'    => $this->editor_id,
665
		) );
666
		$request = new WP_REST_Request( 'DELETE', '/wp/v2/media/' . $attachment_id );
667
		$response = $this->server->dispatch( $request );
668
		$this->assertErrorResponse( 'rest_cannot_delete', $response, 403 );
669
	}
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
	public function test_get_item_schema() {
687
		$request = new WP_REST_Request( 'OPTIONS', '/wp/v2/media' );
688
		$response = $this->server->dispatch( $request );
689
		$data = $response->get_data();
690
		$properties = $data['schema']['properties'];
691
		$this->assertEquals( 22, count( $properties ) );
692
		$this->assertArrayHasKey( 'author', $properties );
693
		$this->assertArrayHasKey( 'alt_text', $properties );
694
		$this->assertArrayHasKey( 'caption', $properties );
695
		$this->assertArrayHasKey( 'description', $properties );
696
		$this->assertArrayHasKey( 'comment_status', $properties );
697
		$this->assertArrayHasKey( 'date', $properties );
698
		$this->assertArrayHasKey( 'date_gmt', $properties );
699
		$this->assertArrayHasKey( 'guid', $properties );
700
		$this->assertArrayHasKey( 'id', $properties );
701
		$this->assertArrayHasKey( 'link', $properties );
702
		$this->assertArrayHasKey( 'media_type', $properties );
703
		$this->assertArrayHasKey( 'mime_type', $properties );
704
		$this->assertArrayHasKey( 'media_details', $properties );
705
		$this->assertArrayHasKey( 'modified', $properties );
706
		$this->assertArrayHasKey( 'modified_gmt', $properties );
707
		$this->assertArrayHasKey( 'post', $properties );
708
		$this->assertArrayHasKey( 'ping_status', $properties );
709
		$this->assertArrayHasKey( 'status', $properties );
710
		$this->assertArrayHasKey( 'slug', $properties );
711
		$this->assertArrayHasKey( 'source_url', $properties );
712
		$this->assertArrayHasKey( 'title', $properties );
713
		$this->assertArrayHasKey( 'type', $properties );
714
	}
715
716
	public function test_get_additional_field_registration() {
717
718
		$schema = array(
719
			'type'        => 'integer',
720
			'description' => 'Some integer of mine',
721
			'enum'        => array( 1, 2, 3, 4 ),
722
			'context'     => array( 'view', 'edit' ),
723
		);
724
725
		register_rest_field( 'attachment', 'my_custom_int', array(
726
			'schema'          => $schema,
727
			'get_callback'    => array( $this, 'additional_field_get_callback' ),
728
		) );
729
730
		$request = new WP_REST_Request( 'OPTIONS', '/wp/v2/media' );
731
732
		$response = $this->server->dispatch( $request );
733
		$data = $response->get_data();
734
		$this->assertArrayHasKey( 'my_custom_int', $data['schema']['properties'] );
735
		$this->assertEquals( $schema, $data['schema']['properties']['my_custom_int'] );
736
737
		$attachment_id = $this->factory->attachment->create_object( $this->test_file, 0, array(
738
			'post_mime_type' => 'image/jpeg',
739
			'post_excerpt'   => 'A sample caption',
740
		) );
741
742
		$request = new WP_REST_Request( 'GET', '/wp/v2/media/' . $attachment_id );
743
744
		$response = $this->server->dispatch( $request );
745
		$this->assertArrayHasKey( 'my_custom_int', $response->data );
746
747
		global $wp_rest_additional_fields;
748
		$wp_rest_additional_fields = array();
749
	}
750
751
	public function test_additional_field_update_errors() {
752
		$schema = array(
753
			'type'        => 'integer',
754
			'description' => 'Some integer of mine',
755
			'enum'        => array( 1, 2, 3, 4 ),
756
			'context'     => array( 'view', 'edit' ),
757
		);
758
759
		register_rest_field( 'attachment', 'my_custom_int', array(
760
			'schema'          => $schema,
761
			'get_callback'    => array( $this, 'additional_field_get_callback' ),
762
			'update_callback' => array( $this, 'additional_field_update_callback' ),
763
		) );
764
765
		wp_set_current_user( $this->editor_id );
766
		$attachment_id = $this->factory->attachment->create_object( $this->test_file, 0, array(
767
			'post_mime_type' => 'image/jpeg',
768
			'post_excerpt'   => 'A sample caption',
769
			'post_author'    => $this->editor_id,
770
		) );
771
		// Check for error on update.
772
		$request = new WP_REST_Request( 'POST', sprintf( '/wp/v2/media/%d', $attachment_id ) );
773
		$request->set_body_params(array(
774
			'my_custom_int' => 'returnError',
775
		));
776
777
		$response = $this->server->dispatch( $request );
778
779
		$this->assertErrorResponse( 'rest_invalid_param', $response, 400 );
780
781
		global $wp_rest_additional_fields;
782
		$wp_rest_additional_fields = array();
783
	}
784
785
	public function additional_field_get_callback( $object, $request ) {
786
		return 123;
787
	}
788
789
	public function additional_field_update_callback( $value, $attachment ) {
790
		if ( 'returnError' === $value ) {
791
			return new WP_Error( 'rest_invalid_param', 'Testing an error.', array( 'status' => 400 ) );
792
		}
793
	}
794
795
	public function tearDown() {
796
		parent::tearDown();
797
		if ( file_exists( $this->test_file ) ) {
798
			unlink( $this->test_file );
799
		}
800
		if ( file_exists( $this->test_file2 ) ) {
801
			unlink( $this->test_file2 );
802
		}
803
	}
804
805
	protected function check_post_data( $attachment, $data, $context = 'view', $links ) {
806
		parent::check_post_data( $attachment, $data, $context, $links );
807
808
		$this->assertEquals( get_post_meta( $attachment->ID, '_wp_attachment_image_alt', true ), $data['alt_text'] );
809
		$this->assertEquals( $attachment->post_excerpt, $data['caption'] );
810
		$this->assertEquals( $attachment->post_content, $data['description'] );
811
		$this->assertTrue( isset( $data['media_details'] ) );
812
813
		if ( $attachment->post_parent ) {
814
			$this->assertEquals( $attachment->post_parent, $data['post'] );
815
		} else {
816
			$this->assertNull( $data['post'] );
817
		}
818
819
		$this->assertEquals( wp_get_attachment_url( $attachment->ID ), $data['source_url'] );
820
821
	}
822
823
}
824