attachments.php 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526
  1. <?php
  2. /**
  3. * @group post
  4. * @group media
  5. * @group upload
  6. */
  7. class Tests_Post_Attachments extends WP_UnitTestCase {
  8. function tearDown() {
  9. // Remove all uploads.
  10. $this->remove_added_uploads();
  11. parent::tearDown();
  12. }
  13. function test_insert_bogus_image() {
  14. $filename = rand_str() . '.jpg';
  15. $contents = rand_str();
  16. $upload = wp_upload_bits( $filename, null, $contents );
  17. $this->assertTrue( empty( $upload['error'] ) );
  18. }
  19. function test_insert_image_no_thumb() {
  20. // This image is smaller than the thumbnail size so it won't have one.
  21. $filename = ( DIR_TESTDATA . '/images/test-image.jpg' );
  22. $contents = file_get_contents( $filename );
  23. $upload = wp_upload_bits( wp_basename( $filename ), null, $contents );
  24. $this->assertTrue( empty( $upload['error'] ) );
  25. $id = $this->_make_attachment( $upload );
  26. // Intermediate copies should not exist.
  27. $this->assertFalse( image_get_intermediate_size( $id, 'thumbnail' ) );
  28. $this->assertFalse( image_get_intermediate_size( $id, 'medium' ) );
  29. $this->assertFalse( image_get_intermediate_size( $id, 'medium_large' ) );
  30. // medium, medium_large, and full size will both point to the original.
  31. $downsize = image_downsize( $id, 'medium' );
  32. $this->assertSame( wp_basename( $upload['file'] ), wp_basename( $downsize[0] ) );
  33. $this->assertSame( 50, $downsize[1] );
  34. $this->assertSame( 50, $downsize[2] );
  35. $downsize = image_downsize( $id, 'medium_large' );
  36. $this->assertSame( wp_basename( $upload['file'] ), wp_basename( $downsize[0] ) );
  37. $this->assertSame( 50, $downsize[1] );
  38. $this->assertSame( 50, $downsize[2] );
  39. $downsize = image_downsize( $id, 'full' );
  40. $this->assertSame( wp_basename( $upload['file'] ), wp_basename( $downsize[0] ) );
  41. $this->assertSame( 50, $downsize[1] );
  42. $this->assertSame( 50, $downsize[2] );
  43. }
  44. /**
  45. * @requires function imagejpeg
  46. */
  47. function test_insert_image_thumb_only() {
  48. update_option( 'medium_size_w', 0 );
  49. update_option( 'medium_size_h', 0 );
  50. $filename = ( DIR_TESTDATA . '/images/a2-small.jpg' );
  51. $contents = file_get_contents( $filename );
  52. $upload = wp_upload_bits( wp_basename( $filename ), null, $contents );
  53. $this->assertTrue( empty( $upload['error'] ) );
  54. $id = $this->_make_attachment( $upload );
  55. // Intermediate copies should exist: thumbnail only.
  56. $thumb = image_get_intermediate_size( $id, 'thumbnail' );
  57. $this->assertSame( 'a2-small-150x150.jpg', $thumb['file'] );
  58. $uploads = wp_upload_dir();
  59. $this->assertTrue( is_file( $uploads['basedir'] . DIRECTORY_SEPARATOR . $thumb['path'] ) );
  60. $this->assertFalse( image_get_intermediate_size( $id, 'medium' ) );
  61. $this->assertFalse( image_get_intermediate_size( $id, 'medium_large' ) );
  62. // The thumb url should point to the thumbnail intermediate.
  63. $this->assertSame( $thumb['url'], wp_get_attachment_thumb_url( $id ) );
  64. // image_downsize() should return the correct images and sizes.
  65. $downsize = image_downsize( $id, 'thumbnail' );
  66. $this->assertSame( 'a2-small-150x150.jpg', wp_basename( $downsize[0] ) );
  67. $this->assertSame( 150, $downsize[1] );
  68. $this->assertSame( 150, $downsize[2] );
  69. // medium, medium_large, and full will both point to the original.
  70. $downsize = image_downsize( $id, 'medium' );
  71. $this->assertSame( 'a2-small.jpg', wp_basename( $downsize[0] ) );
  72. $this->assertSame( 400, $downsize[1] );
  73. $this->assertSame( 300, $downsize[2] );
  74. $downsize = image_downsize( $id, 'medium_large' );
  75. $this->assertSame( 'a2-small.jpg', wp_basename( $downsize[0] ) );
  76. $this->assertSame( 400, $downsize[1] );
  77. $this->assertSame( 300, $downsize[2] );
  78. $downsize = image_downsize( $id, 'full' );
  79. $this->assertSame( 'a2-small.jpg', wp_basename( $downsize[0] ) );
  80. $this->assertSame( 400, $downsize[1] );
  81. $this->assertSame( 300, $downsize[2] );
  82. }
  83. /**
  84. * @requires function imagejpeg
  85. */
  86. function test_insert_image_medium_sizes() {
  87. update_option( 'medium_size_w', 400 );
  88. update_option( 'medium_size_h', 0 );
  89. update_option( 'medium_large_size_w', 600 );
  90. update_option( 'medium_large_size_h', 0 );
  91. $filename = ( DIR_TESTDATA . '/images/2007-06-17DSC_4173.JPG' );
  92. $contents = file_get_contents( $filename );
  93. $upload = wp_upload_bits( wp_basename( $filename ), null, $contents );
  94. $this->assertTrue( empty( $upload['error'] ) );
  95. $id = $this->_make_attachment( $upload );
  96. $uploads = wp_upload_dir();
  97. // Intermediate copies should exist: thumbnail and medium.
  98. $thumb = image_get_intermediate_size( $id, 'thumbnail' );
  99. $this->assertSame( '2007-06-17DSC_4173-150x150.jpg', $thumb['file'] );
  100. $this->assertTrue( is_file( $uploads['basedir'] . DIRECTORY_SEPARATOR . $thumb['path'] ) );
  101. $medium = image_get_intermediate_size( $id, 'medium' );
  102. $this->assertSame( '2007-06-17DSC_4173-400x602.jpg', $medium['file'] );
  103. $this->assertTrue( is_file( $uploads['basedir'] . DIRECTORY_SEPARATOR . $medium['path'] ) );
  104. $medium_large = image_get_intermediate_size( $id, 'medium_large' );
  105. $this->assertSame( '2007-06-17DSC_4173-600x904.jpg', $medium_large['file'] );
  106. $this->assertTrue( is_file( $uploads['basedir'] . DIRECTORY_SEPARATOR . $medium_large['path'] ) );
  107. // The thumb url should point to the thumbnail intermediate.
  108. $this->assertSame( $thumb['url'], wp_get_attachment_thumb_url( $id ) );
  109. // image_downsize() should return the correct images and sizes.
  110. $downsize = image_downsize( $id, 'thumbnail' );
  111. $this->assertSame( '2007-06-17DSC_4173-150x150.jpg', wp_basename( $downsize[0] ) );
  112. $this->assertSame( 150, $downsize[1] );
  113. $this->assertSame( 150, $downsize[2] );
  114. $downsize = image_downsize( $id, 'medium' );
  115. $this->assertSame( '2007-06-17DSC_4173-400x602.jpg', wp_basename( $downsize[0] ) );
  116. $this->assertSame( 400, $downsize[1] );
  117. $this->assertSame( 602, $downsize[2] );
  118. $downsize = image_downsize( $id, 'medium_large' );
  119. $this->assertSame( '2007-06-17DSC_4173-600x904.jpg', wp_basename( $downsize[0] ) );
  120. $this->assertSame( 600, $downsize[1] );
  121. $this->assertSame( 904, $downsize[2] );
  122. $downsize = image_downsize( $id, 'full' );
  123. $this->assertSame( '2007-06-17DSC_4173.jpg', wp_basename( $downsize[0] ) );
  124. $this->assertSame( 680, $downsize[1] );
  125. $this->assertSame( 1024, $downsize[2] );
  126. }
  127. /**
  128. * @requires function imagejpeg
  129. */
  130. function test_insert_image_delete() {
  131. update_option( 'medium_size_w', 400 );
  132. update_option( 'medium_size_h', 0 );
  133. update_option( 'medium_large_size_w', 600 );
  134. update_option( 'medium_large_size_h', 0 );
  135. $filename = ( DIR_TESTDATA . '/images/2007-06-17DSC_4173.JPG' );
  136. $contents = file_get_contents( $filename );
  137. $upload = wp_upload_bits( wp_basename( $filename ), null, $contents );
  138. $this->assertTrue( empty( $upload['error'] ) );
  139. $id = $this->_make_attachment( $upload );
  140. $uploads = wp_upload_dir();
  141. // Check that the file and intermediates exist.
  142. $thumb = image_get_intermediate_size( $id, 'thumbnail' );
  143. $this->assertSame( '2007-06-17DSC_4173-150x150.jpg', $thumb['file'] );
  144. $this->assertTrue( is_file( $uploads['basedir'] . DIRECTORY_SEPARATOR . $thumb['path'] ) );
  145. $medium = image_get_intermediate_size( $id, 'medium' );
  146. $this->assertSame( '2007-06-17DSC_4173-400x602.jpg', $medium['file'] );
  147. $this->assertTrue( is_file( $uploads['basedir'] . DIRECTORY_SEPARATOR . $medium['path'] ) );
  148. $medium_large = image_get_intermediate_size( $id, 'medium_large' );
  149. $this->assertSame( '2007-06-17DSC_4173-600x904.jpg', $medium_large['file'] );
  150. $this->assertTrue( is_file( $uploads['basedir'] . DIRECTORY_SEPARATOR . $medium_large['path'] ) );
  151. $meta = wp_get_attachment_metadata( $id );
  152. $original = $meta['file'];
  153. $this->assertTrue( is_file( $uploads['basedir'] . DIRECTORY_SEPARATOR . $original ) );
  154. // Now delete the attachment and make sure all files are gone.
  155. wp_delete_attachment( $id );
  156. $this->assertFalse( is_file( $thumb['path'] ) );
  157. $this->assertFalse( is_file( $medium['path'] ) );
  158. $this->assertFalse( is_file( $medium_large['path'] ) );
  159. $this->assertFalse( is_file( $original ) );
  160. }
  161. /**
  162. * GUID should never be empty
  163. *
  164. * @ticket 18310
  165. * @ticket 21963
  166. */
  167. function test_insert_image_without_guid() {
  168. // This image is smaller than the thumbnail size so it won't have one.
  169. $filename = ( DIR_TESTDATA . '/images/test-image.jpg' );
  170. $contents = file_get_contents( $filename );
  171. $upload = wp_upload_bits( wp_basename( $filename ), null, $contents );
  172. $this->assertTrue( empty( $upload['error'] ) );
  173. $upload['url'] = '';
  174. $id = $this->_make_attachment( $upload );
  175. $guid = get_the_guid( $id );
  176. $this->assertFalse( empty( $guid ) );
  177. }
  178. /**
  179. * @ticket 21963
  180. */
  181. function test_update_attachment_fields() {
  182. $filename = ( DIR_TESTDATA . '/images/test-image.jpg' );
  183. $contents = file_get_contents( $filename );
  184. $upload = wp_upload_bits( wp_basename( $filename ), null, $contents );
  185. $this->assertTrue( empty( $upload['error'] ) );
  186. $id = $this->_make_attachment( $upload );
  187. $attached_file = get_post_meta( $id, '_wp_attached_file', true );
  188. $post = get_post( $id, ARRAY_A );
  189. $post['post_title'] = 'title';
  190. $post['post_excerpt'] = 'caption';
  191. $post['post_content'] = 'description';
  192. wp_update_post( $post );
  193. // Make sure the update didn't remove the attached file.
  194. $this->assertSame( $attached_file, get_post_meta( $id, '_wp_attached_file', true ) );
  195. }
  196. /**
  197. * @ticket 29646
  198. */
  199. function test_update_orphan_attachment_parent() {
  200. $filename = ( DIR_TESTDATA . '/images/test-image.jpg' );
  201. $contents = file_get_contents( $filename );
  202. $upload = wp_upload_bits( wp_basename( $filename ), null, $contents );
  203. $this->assertTrue( empty( $upload['error'] ) );
  204. $attachment_id = $this->_make_attachment( $upload );
  205. // Assert that the attachment is an orphan.
  206. $attachment = get_post( $attachment_id );
  207. $this->assertSame( $attachment->post_parent, 0 );
  208. $post_id = wp_insert_post(
  209. array(
  210. 'post_content' => rand_str(),
  211. 'post_title' => rand_str(),
  212. )
  213. );
  214. // Assert that the attachment has a parent.
  215. wp_insert_attachment( $attachment, '', $post_id );
  216. $attachment = get_post( $attachment_id );
  217. $this->assertSame( $attachment->post_parent, $post_id );
  218. }
  219. /**
  220. * @ticket 15928
  221. */
  222. public function test_wp_get_attachment_url_should_not_force_https_when_current_page_is_non_ssl_and_siteurl_is_non_ssl() {
  223. $siteurl = get_option( 'siteurl' );
  224. update_option( 'siteurl', set_url_scheme( $siteurl, 'http' ) );
  225. $filename = DIR_TESTDATA . '/images/test-image.jpg';
  226. $contents = file_get_contents( $filename );
  227. $upload = wp_upload_bits( wp_basename( $filename ), null, $contents );
  228. $this->assertTrue( empty( $upload['error'] ) );
  229. // Set attachment ID.
  230. $attachment_id = $this->_make_attachment( $upload );
  231. $_SERVER['HTTPS'] = 'off';
  232. $url = wp_get_attachment_url( $attachment_id );
  233. $this->assertSame( 'http', parse_url( $url, PHP_URL_SCHEME ) );
  234. }
  235. /**
  236. * @ticket 15928
  237. *
  238. * This situation (current request is non-SSL but siteurl is https) should never arise.
  239. */
  240. public function test_wp_get_attachment_url_should_not_force_https_when_current_page_is_non_ssl_and_siteurl_is_ssl() {
  241. $siteurl = get_option( 'siteurl' );
  242. update_option( 'siteurl', set_url_scheme( $siteurl, 'https' ) );
  243. $filename = DIR_TESTDATA . '/images/test-image.jpg';
  244. $contents = file_get_contents( $filename );
  245. $upload = wp_upload_bits( wp_basename( $filename ), null, $contents );
  246. $this->assertTrue( empty( $upload['error'] ) );
  247. // Set attachment ID.
  248. $attachment_id = $this->_make_attachment( $upload );
  249. $_SERVER['HTTPS'] = 'off';
  250. $url = wp_get_attachment_url( $attachment_id );
  251. $this->assertSame( 'http', parse_url( $url, PHP_URL_SCHEME ) );
  252. }
  253. /**
  254. * @ticket 15928
  255. *
  256. * Canonical siteurl is non-SSL, but SSL support is available/optional.
  257. */
  258. public function test_wp_get_attachment_url_should_force_https_with_https_on_same_host_when_siteurl_is_non_ssl_but_ssl_is_available() {
  259. $siteurl = get_option( 'siteurl' );
  260. update_option( 'siteurl', set_url_scheme( $siteurl, 'http' ) );
  261. $filename = ( DIR_TESTDATA . '/images/test-image.jpg' );
  262. $contents = file_get_contents( $filename );
  263. $upload = wp_upload_bits( wp_basename( $filename ), null, $contents );
  264. $this->assertTrue( empty( $upload['error'] ) );
  265. // Set attachment ID.
  266. $attachment_id = $this->_make_attachment( $upload );
  267. $_SERVER['HTTPS'] = 'on';
  268. // Ensure that server host matches the host of wp_upload_dir().
  269. $upload_dir = wp_upload_dir();
  270. $_SERVER['HTTP_HOST'] = parse_url( $upload_dir['baseurl'], PHP_URL_HOST );
  271. // Test that wp_get_attachemt_url returns with https scheme.
  272. $url = wp_get_attachment_url( $attachment_id );
  273. $this->assertSame( 'https', parse_url( $url, PHP_URL_SCHEME ) );
  274. }
  275. /**
  276. * @ticket 15928
  277. */
  278. public function test_wp_get_attachment_url_with_https_on_same_host_when_siteurl_is_https() {
  279. $siteurl = get_option( 'siteurl' );
  280. update_option( 'siteurl', set_url_scheme( $siteurl, 'https' ) );
  281. $filename = ( DIR_TESTDATA . '/images/test-image.jpg' );
  282. $contents = file_get_contents( $filename );
  283. $upload = wp_upload_bits( wp_basename( $filename ), null, $contents );
  284. $this->assertTrue( empty( $upload['error'] ) );
  285. // Set attachment ID.
  286. $attachment_id = $this->_make_attachment( $upload );
  287. $_SERVER['HTTPS'] = 'on';
  288. // Ensure that server host matches the host of wp_upload_dir().
  289. $upload_dir = wp_upload_dir();
  290. $_SERVER['HTTP_HOST'] = parse_url( $upload_dir['baseurl'], PHP_URL_HOST );
  291. // Test that wp_get_attachemt_url returns with https scheme.
  292. $url = wp_get_attachment_url( $attachment_id );
  293. $this->assertSame( 'https', parse_url( $url, PHP_URL_SCHEME ) );
  294. }
  295. /**
  296. * @ticket 15928
  297. */
  298. public function test_wp_get_attachment_url_should_not_force_https_when_administering_over_https_but_siteurl_is_not_https() {
  299. $siteurl = get_option( 'siteurl' );
  300. update_option( 'siteurl', set_url_scheme( $siteurl, 'http' ) );
  301. $filename = ( DIR_TESTDATA . '/images/test-image.jpg' );
  302. $contents = file_get_contents( $filename );
  303. $upload = wp_upload_bits( wp_basename( $filename ), null, $contents );
  304. $this->assertTrue( empty( $upload['error'] ) );
  305. // Set attachment ID.
  306. $attachment_id = $this->_make_attachment( $upload );
  307. $_SERVER['HTTPS'] = 'on';
  308. set_current_screen( 'dashboard' );
  309. $url = wp_get_attachment_url( $attachment_id );
  310. // Cleanup.
  311. set_current_screen( 'front' );
  312. $this->assertSame( set_url_scheme( $url, 'http' ), $url );
  313. }
  314. /**
  315. * @ticket 15928
  316. */
  317. public function test_wp_get_attachment_url_should_force_https_when_administering_over_https_and_siteurl_is_https() {
  318. // Set https upload URL.
  319. add_filter( 'upload_dir', '_upload_dir_https' );
  320. $filename = ( DIR_TESTDATA . '/images/test-image.jpg' );
  321. $contents = file_get_contents( $filename );
  322. $upload = wp_upload_bits( wp_basename( $filename ), null, $contents );
  323. $this->assertTrue( empty( $upload['error'] ) );
  324. // Set attachment ID.
  325. $attachment_id = $this->_make_attachment( $upload );
  326. $_SERVER['HTTPS'] = 'on';
  327. set_current_screen( 'dashboard' );
  328. $url = wp_get_attachment_url( $attachment_id );
  329. // Cleanup.
  330. set_current_screen( 'front' );
  331. remove_filter( 'upload_dir', '_upload_dir_https' );
  332. $this->assertSame( 'https', parse_url( $url, PHP_URL_SCHEME ) );
  333. }
  334. public function test_wp_attachment_is() {
  335. $filename = DIR_TESTDATA . '/images/test-image.jpg';
  336. $contents = file_get_contents( $filename );
  337. $upload = wp_upload_bits( wp_basename( $filename ), null, $contents );
  338. $attachment_id = $this->_make_attachment( $upload );
  339. $this->assertTrue( wp_attachment_is_image( $attachment_id ) );
  340. $this->assertTrue( wp_attachment_is( 'image', $attachment_id ) );
  341. $this->assertFalse( wp_attachment_is( 'audio', $attachment_id ) );
  342. $this->assertFalse( wp_attachment_is( 'video', $attachment_id ) );
  343. }
  344. public function test_wp_attachment_is_default() {
  345. // On Multisite, psd is not an allowed mime type by default.
  346. if ( is_multisite() ) {
  347. add_filter( 'upload_mimes', array( $this, 'allow_psd_mime_type' ), 10, 2 );
  348. }
  349. $filename = DIR_TESTDATA . '/images/test-image.psd';
  350. $contents = file_get_contents( $filename );
  351. $upload = wp_upload_bits( wp_basename( $filename ), null, $contents );
  352. $attachment_id = $this->_make_attachment( $upload );
  353. $this->assertFalse( wp_attachment_is_image( $attachment_id ) );
  354. $this->assertTrue( wp_attachment_is( 'psd', $attachment_id ) );
  355. $this->assertFalse( wp_attachment_is( 'audio', $attachment_id ) );
  356. $this->assertFalse( wp_attachment_is( 'video', $attachment_id ) );
  357. if ( is_multisite() ) {
  358. remove_filter( 'upload_mimes', array( $this, 'allow_psd_mime_type' ), 10, 2 );
  359. }
  360. }
  361. public function test_upload_mimes_filter_is_applied() {
  362. $filename = DIR_TESTDATA . '/images/test-image.jpg';
  363. $contents = file_get_contents( $filename );
  364. $upload = wp_upload_bits( wp_basename( $filename ), null, $contents );
  365. $this->assertFalse( $upload['error'] );
  366. add_filter( 'upload_mimes', array( $this, 'disallow_jpg_mime_type' ) );
  367. $upload = wp_upload_bits( wp_basename( $filename ), null, $contents );
  368. remove_filter( 'upload_mimes', array( $this, 'disallow_jpg_mime_type' ) );
  369. $this->assertNotEmpty( $upload['error'] );
  370. }
  371. public function allow_psd_mime_type( $mimes ) {
  372. $mimes['psd'] = 'application/octet-stream';
  373. return $mimes;
  374. }
  375. public function disallow_jpg_mime_type( $mimes ) {
  376. unset( $mimes['jpg|jpeg|jpe'] );
  377. return $mimes;
  378. }
  379. /**
  380. * @ticket 33012
  381. */
  382. public function test_wp_mime_type_icon() {
  383. $icon = wp_mime_type_icon();
  384. $this->assertContains( 'images/media/default.png', $icon );
  385. }
  386. /**
  387. * @ticket 33012
  388. */
  389. public function test_wp_mime_type_icon_video() {
  390. $icon = wp_mime_type_icon( 'video/mp4' );
  391. $this->assertContains( 'images/media/video.png', $icon );
  392. }
  393. }