PageRenderTime 54ms CodeModel.GetById 20ms RepoModel.GetById 0ms app.codeStats 0ms

/wp-includes/media.php

https://bitbucket.org/acipriani/madeinapulia.com
PHP | 3324 lines | 1643 code | 355 blank | 1326 comment | 328 complexity | f558c13bfd84f79de2779a5847b8c459 MD5 | raw file
Possible License(s): GPL-3.0, MIT, BSD-3-Clause, LGPL-2.1, GPL-2.0, Apache-2.0

Large files files are truncated, but you can click here to view the full file

  1. <?php
  2. /**
  3. * WordPress API for media display.
  4. *
  5. * @package WordPress
  6. * @subpackage Media
  7. */
  8. /**
  9. * Scale down the default size of an image.
  10. *
  11. * This is so that the image is a better fit for the editor and theme.
  12. *
  13. * The `$size` parameter accepts either an array or a string. The supported string
  14. * values are 'thumb' or 'thumbnail' for the given thumbnail size or defaults at
  15. * 128 width and 96 height in pixels. Also supported for the string value is
  16. * 'medium' and 'full'. The 'full' isn't actually supported, but any value other
  17. * than the supported will result in the content_width size or 500 if that is
  18. * not set.
  19. *
  20. * Finally, there is a filter named {@see 'editor_max_image_size'}, that will be
  21. * called on the calculated array for width and height, respectively. The second
  22. * parameter will be the value that was in the $size parameter. The returned
  23. * type for the hook is an array with the width as the first element and the
  24. * height as the second element.
  25. *
  26. * @since 2.5.0
  27. *
  28. * @param int $width Width of the image in pixels.
  29. * @param int $height Height of the image in pixels.
  30. * @param string|array $size Optional. Size or array of sizes of what the result image
  31. * should be. Accepts any valid image size name. Default 'medium'.
  32. * @param string $context Optional. Could be 'display' (like in a theme) or 'edit'
  33. * (like inserting into an editor). Default null.
  34. * @return array Width and height of what the result image should resize to.
  35. */
  36. function image_constrain_size_for_editor( $width, $height, $size = 'medium', $context = null ) {
  37. global $content_width, $_wp_additional_image_sizes;
  38. if ( ! $context )
  39. $context = is_admin() ? 'edit' : 'display';
  40. if ( is_array($size) ) {
  41. $max_width = $size[0];
  42. $max_height = $size[1];
  43. }
  44. elseif ( $size == 'thumb' || $size == 'thumbnail' ) {
  45. $max_width = intval(get_option('thumbnail_size_w'));
  46. $max_height = intval(get_option('thumbnail_size_h'));
  47. // last chance thumbnail size defaults
  48. if ( !$max_width && !$max_height ) {
  49. $max_width = 128;
  50. $max_height = 96;
  51. }
  52. }
  53. elseif ( $size == 'medium' ) {
  54. $max_width = intval(get_option('medium_size_w'));
  55. $max_height = intval(get_option('medium_size_h'));
  56. // if no width is set, default to the theme content width if available
  57. }
  58. elseif ( $size == 'large' ) {
  59. // We're inserting a large size image into the editor. If it's a really
  60. // big image we'll scale it down to fit reasonably within the editor
  61. // itself, and within the theme's content width if it's known. The user
  62. // can resize it in the editor if they wish.
  63. $max_width = intval(get_option('large_size_w'));
  64. $max_height = intval(get_option('large_size_h'));
  65. if ( intval($content_width) > 0 )
  66. $max_width = min( intval($content_width), $max_width );
  67. } elseif ( isset( $_wp_additional_image_sizes ) && count( $_wp_additional_image_sizes ) && in_array( $size, array_keys( $_wp_additional_image_sizes ) ) ) {
  68. $max_width = intval( $_wp_additional_image_sizes[$size]['width'] );
  69. $max_height = intval( $_wp_additional_image_sizes[$size]['height'] );
  70. if ( intval($content_width) > 0 && 'edit' == $context ) // Only in admin. Assume that theme authors know what they're doing.
  71. $max_width = min( intval($content_width), $max_width );
  72. }
  73. // $size == 'full' has no constraint
  74. else {
  75. $max_width = $width;
  76. $max_height = $height;
  77. }
  78. /**
  79. * Filter the maximum image size dimensions for the editor.
  80. *
  81. * @since 2.5.0
  82. *
  83. * @param array $max_image_size An array with the width as the first element,
  84. * and the height as the second element.
  85. * @param string|array $size Size of what the result image should be.
  86. * @param string $context The context the image is being resized for.
  87. * Possible values are 'display' (like in a theme)
  88. * or 'edit' (like inserting into an editor).
  89. */
  90. list( $max_width, $max_height ) = apply_filters( 'editor_max_image_size', array( $max_width, $max_height ), $size, $context );
  91. return wp_constrain_dimensions( $width, $height, $max_width, $max_height );
  92. }
  93. /**
  94. * Retrieve width and height attributes using given width and height values.
  95. *
  96. * Both attributes are required in the sense that both parameters must have a
  97. * value, but are optional in that if you set them to false or null, then they
  98. * will not be added to the returned string.
  99. *
  100. * You can set the value using a string, but it will only take numeric values.
  101. * If you wish to put 'px' after the numbers, then it will be stripped out of
  102. * the return.
  103. *
  104. * @since 2.5.0
  105. *
  106. * @param int|string $width Optional. Width attribute value.
  107. * @param int|string $height Optional. Height attribute value.
  108. * @return string HTML attributes for width and, or height.
  109. */
  110. function image_hwstring($width, $height) {
  111. $out = '';
  112. if ($width)
  113. $out .= 'width="'.intval($width).'" ';
  114. if ($height)
  115. $out .= 'height="'.intval($height).'" ';
  116. return $out;
  117. }
  118. /**
  119. * Scale an image to fit a particular size (such as 'thumb' or 'medium').
  120. *
  121. * Array with image url, width, height, and whether is intermediate size, in
  122. * that order is returned on success is returned. $is_intermediate is true if
  123. * $url is a resized image, false if it is the original.
  124. *
  125. * The URL might be the original image, or it might be a resized version. This
  126. * function won't create a new resized copy, it will just return an already
  127. * resized one if it exists.
  128. *
  129. * A plugin may use the 'image_downsize' filter to hook into and offer image
  130. * resizing services for images. The hook must return an array with the same
  131. * elements that are returned in the function. The first element being the URL
  132. * to the new image that was resized.
  133. *
  134. * @since 2.5.0
  135. *
  136. * @param int $id Attachment ID for image.
  137. * @param array|string $size Optional, default is 'medium'. Size of image, either array or string.
  138. * @return bool|array False on failure, array on success.
  139. */
  140. function image_downsize($id, $size = 'medium') {
  141. if ( !wp_attachment_is_image($id) )
  142. return false;
  143. /**
  144. * Filter whether to preempt the output of image_downsize().
  145. *
  146. * Passing a truthy value to the filter will effectively short-circuit
  147. * down-sizing the image, returning that value as output instead.
  148. *
  149. * @since 2.5.0
  150. *
  151. * @param bool $downsize Whether to short-circuit the image downsize. Default false.
  152. * @param int $id Attachment ID for image.
  153. * @param array|string $size Size of image, either array or string. Default 'medium'.
  154. */
  155. if ( $out = apply_filters( 'image_downsize', false, $id, $size ) ) {
  156. return $out;
  157. }
  158. $img_url = wp_get_attachment_url($id);
  159. $meta = wp_get_attachment_metadata($id);
  160. $width = $height = 0;
  161. $is_intermediate = false;
  162. $img_url_basename = wp_basename($img_url);
  163. // try for a new style intermediate size
  164. if ( $intermediate = image_get_intermediate_size($id, $size) ) {
  165. $img_url = str_replace($img_url_basename, $intermediate['file'], $img_url);
  166. $width = $intermediate['width'];
  167. $height = $intermediate['height'];
  168. $is_intermediate = true;
  169. }
  170. elseif ( $size == 'thumbnail' ) {
  171. // fall back to the old thumbnail
  172. if ( ($thumb_file = wp_get_attachment_thumb_file($id)) && $info = getimagesize($thumb_file) ) {
  173. $img_url = str_replace($img_url_basename, wp_basename($thumb_file), $img_url);
  174. $width = $info[0];
  175. $height = $info[1];
  176. $is_intermediate = true;
  177. }
  178. }
  179. if ( !$width && !$height && isset( $meta['width'], $meta['height'] ) ) {
  180. // any other type: use the real image
  181. $width = $meta['width'];
  182. $height = $meta['height'];
  183. }
  184. if ( $img_url) {
  185. // we have the actual image size, but might need to further constrain it if content_width is narrower
  186. list( $width, $height ) = image_constrain_size_for_editor( $width, $height, $size );
  187. return array( $img_url, $width, $height, $is_intermediate );
  188. }
  189. return false;
  190. }
  191. /**
  192. * Register a new image size.
  193. *
  194. * Cropping behavior for the image size is dependent on the value of $crop:
  195. * 1. If false (default), images will be scaled, not cropped.
  196. * 2. If an array in the form of array( x_crop_position, y_crop_position ):
  197. * - x_crop_position accepts 'left' 'center', or 'right'.
  198. * - y_crop_position accepts 'top', 'center', or 'bottom'.
  199. * Images will be cropped to the specified dimensions within the defined crop area.
  200. * 3. If true, images will be cropped to the specified dimensions using center positions.
  201. *
  202. * @since 2.9.0
  203. *
  204. * @global array $_wp_additional_image_sizes Associative array of additional image sizes.
  205. *
  206. * @param string $name Image size identifier.
  207. * @param int $width Image width in pixels.
  208. * @param int $height Image height in pixels.
  209. * @param bool|array $crop Optional. Whether to crop images to specified height and width or resize.
  210. * An array can specify positioning of the crop area. Default false.
  211. */
  212. function add_image_size( $name, $width = 0, $height = 0, $crop = false ) {
  213. global $_wp_additional_image_sizes;
  214. $_wp_additional_image_sizes[ $name ] = array(
  215. 'width' => absint( $width ),
  216. 'height' => absint( $height ),
  217. 'crop' => $crop,
  218. );
  219. }
  220. /**
  221. * Check if an image size exists.
  222. *
  223. * @since 3.9.0
  224. *
  225. * @param string $name The image size to check.
  226. * @return bool True if the image size exists, false if not.
  227. */
  228. function has_image_size( $name ) {
  229. global $_wp_additional_image_sizes;
  230. return isset( $_wp_additional_image_sizes[ $name ] );
  231. }
  232. /**
  233. * Remove a new image size.
  234. *
  235. * @since 3.9.0
  236. *
  237. * @param string $name The image size to remove.
  238. * @return bool True if the image size was successfully removed, false on failure.
  239. */
  240. function remove_image_size( $name ) {
  241. global $_wp_additional_image_sizes;
  242. if ( isset( $_wp_additional_image_sizes[ $name ] ) ) {
  243. unset( $_wp_additional_image_sizes[ $name ] );
  244. return true;
  245. }
  246. return false;
  247. }
  248. /**
  249. * Registers an image size for the post thumbnail.
  250. *
  251. * @since 2.9.0
  252. *
  253. * @see add_image_size() for details on cropping behavior.
  254. *
  255. * @param int $width Image width in pixels.
  256. * @param int $height Image height in pixels.
  257. * @param bool|array $crop Optional. Whether to crop images to specified height and width or resize.
  258. * An array can specify positioning of the crop area. Default false.
  259. */
  260. function set_post_thumbnail_size( $width = 0, $height = 0, $crop = false ) {
  261. add_image_size( 'post-thumbnail', $width, $height, $crop );
  262. }
  263. /**
  264. * An <img src /> tag for an image attachment, scaling it down if requested.
  265. *
  266. * The filter 'get_image_tag_class' allows for changing the class name for the
  267. * image without having to use regular expressions on the HTML content. The
  268. * parameters are: what WordPress will use for the class, the Attachment ID,
  269. * image align value, and the size the image should be.
  270. *
  271. * The second filter 'get_image_tag' has the HTML content, which can then be
  272. * further manipulated by a plugin to change all attribute values and even HTML
  273. * content.
  274. *
  275. * @since 2.5.0
  276. *
  277. * @param int $id Attachment ID.
  278. * @param string $alt Image Description for the alt attribute.
  279. * @param string $title Image Description for the title attribute.
  280. * @param string $align Part of the class name for aligning the image.
  281. * @param string $size Optional. Default is 'medium'.
  282. * @return string HTML IMG element for given image attachment
  283. */
  284. function get_image_tag($id, $alt, $title, $align, $size='medium') {
  285. list( $img_src, $width, $height ) = image_downsize($id, $size);
  286. $hwstring = image_hwstring($width, $height);
  287. $title = $title ? 'title="' . esc_attr( $title ) . '" ' : '';
  288. $class = 'align' . esc_attr($align) .' size-' . esc_attr($size) . ' wp-image-' . $id;
  289. /**
  290. * Filter the value of the attachment's image tag class attribute.
  291. *
  292. * @since 2.6.0
  293. *
  294. * @param string $class CSS class name or space-separated list of classes.
  295. * @param int $id Attachment ID.
  296. * @param string $align Part of the class name for aligning the image.
  297. * @param string $size Optional. Default is 'medium'.
  298. */
  299. $class = apply_filters( 'get_image_tag_class', $class, $id, $align, $size );
  300. $html = '<img src="' . esc_attr($img_src) . '" alt="' . esc_attr($alt) . '" ' . $title . $hwstring . 'class="' . $class . '" />';
  301. /**
  302. * Filter the HTML content for the image tag.
  303. *
  304. * @since 2.6.0
  305. *
  306. * @param string $html HTML content for the image.
  307. * @param int $id Attachment ID.
  308. * @param string $alt Alternate text.
  309. * @param string $title Attachment title.
  310. * @param string $align Part of the class name for aligning the image.
  311. * @param string $size Optional. Default is 'medium'.
  312. */
  313. $html = apply_filters( 'get_image_tag', $html, $id, $alt, $title, $align, $size );
  314. return $html;
  315. }
  316. /**
  317. * Calculates the new dimensions for a downsampled image.
  318. *
  319. * If either width or height are empty, no constraint is applied on
  320. * that dimension.
  321. *
  322. * @since 2.5.0
  323. *
  324. * @param int $current_width Current width of the image.
  325. * @param int $current_height Current height of the image.
  326. * @param int $max_width Optional. Maximum wanted width.
  327. * @param int $max_height Optional. Maximum wanted height.
  328. * @return array First item is the width, the second item is the height.
  329. */
  330. function wp_constrain_dimensions( $current_width, $current_height, $max_width=0, $max_height=0 ) {
  331. if ( !$max_width and !$max_height )
  332. return array( $current_width, $current_height );
  333. $width_ratio = $height_ratio = 1.0;
  334. $did_width = $did_height = false;
  335. if ( $max_width > 0 && $current_width > 0 && $current_width > $max_width ) {
  336. $width_ratio = $max_width / $current_width;
  337. $did_width = true;
  338. }
  339. if ( $max_height > 0 && $current_height > 0 && $current_height > $max_height ) {
  340. $height_ratio = $max_height / $current_height;
  341. $did_height = true;
  342. }
  343. // Calculate the larger/smaller ratios
  344. $smaller_ratio = min( $width_ratio, $height_ratio );
  345. $larger_ratio = max( $width_ratio, $height_ratio );
  346. if ( (int) round( $current_width * $larger_ratio ) > $max_width || (int) round( $current_height * $larger_ratio ) > $max_height ) {
  347. // The larger ratio is too big. It would result in an overflow.
  348. $ratio = $smaller_ratio;
  349. } else {
  350. // The larger ratio fits, and is likely to be a more "snug" fit.
  351. $ratio = $larger_ratio;
  352. }
  353. // Very small dimensions may result in 0, 1 should be the minimum.
  354. $w = max ( 1, (int) round( $current_width * $ratio ) );
  355. $h = max ( 1, (int) round( $current_height * $ratio ) );
  356. // Sometimes, due to rounding, we'll end up with a result like this: 465x700 in a 177x177 box is 117x176... a pixel short
  357. // We also have issues with recursive calls resulting in an ever-changing result. Constraining to the result of a constraint should yield the original result.
  358. // Thus we look for dimensions that are one pixel shy of the max value and bump them up
  359. // Note: $did_width means it is possible $smaller_ratio == $width_ratio.
  360. if ( $did_width && $w == $max_width - 1 ) {
  361. $w = $max_width; // Round it up
  362. }
  363. // Note: $did_height means it is possible $smaller_ratio == $height_ratio.
  364. if ( $did_height && $h == $max_height - 1 ) {
  365. $h = $max_height; // Round it up
  366. }
  367. return apply_filters( 'wp_constrain_dimensions', array( $w, $h ), $current_width, $current_height, $max_width, $max_height );
  368. }
  369. /**
  370. * Retrieve calculated resize dimensions for use in WP_Image_Editor.
  371. *
  372. * Calculates dimensions and coordinates for a resized image that fits
  373. * within a specified width and height.
  374. *
  375. * Cropping behavior is dependent on the value of $crop:
  376. * 1. If false (default), images will not be cropped.
  377. * 2. If an array in the form of array( x_crop_position, y_crop_position ):
  378. * - x_crop_position accepts 'left' 'center', or 'right'.
  379. * - y_crop_position accepts 'top', 'center', or 'bottom'.
  380. * Images will be cropped to the specified dimensions within the defined crop area.
  381. * 3. If true, images will be cropped to the specified dimensions using center positions.
  382. *
  383. * @since 2.5.0
  384. *
  385. * @param int $orig_w Original width in pixels.
  386. * @param int $orig_h Original height in pixels.
  387. * @param int $dest_w New width in pixels.
  388. * @param int $dest_h New height in pixels.
  389. * @param bool|array $crop Optional. Whether to crop image to specified height and width or resize.
  390. * An array can specify positioning of the crop area. Default false.
  391. * @return bool|array False on failure. Returned array matches parameters for `imagecopyresampled()`.
  392. */
  393. function image_resize_dimensions($orig_w, $orig_h, $dest_w, $dest_h, $crop = false) {
  394. if ($orig_w <= 0 || $orig_h <= 0)
  395. return false;
  396. // at least one of dest_w or dest_h must be specific
  397. if ($dest_w <= 0 && $dest_h <= 0)
  398. return false;
  399. /**
  400. * Filter whether to preempt calculating the image resize dimensions.
  401. *
  402. * Passing a non-null value to the filter will effectively short-circuit
  403. * image_resize_dimensions(), returning that value instead.
  404. *
  405. * @since 3.4.0
  406. *
  407. * @param null|mixed $null Whether to preempt output of the resize dimensions.
  408. * @param int $orig_w Original width in pixels.
  409. * @param int $orig_h Original height in pixels.
  410. * @param int $dest_w New width in pixels.
  411. * @param int $dest_h New height in pixels.
  412. * @param bool|array $crop Whether to crop image to specified height and width or resize.
  413. * An array can specify positioning of the crop area. Default false.
  414. */
  415. $output = apply_filters( 'image_resize_dimensions', null, $orig_w, $orig_h, $dest_w, $dest_h, $crop );
  416. if ( null !== $output )
  417. return $output;
  418. if ( $crop ) {
  419. // crop the largest possible portion of the original image that we can size to $dest_w x $dest_h
  420. $aspect_ratio = $orig_w / $orig_h;
  421. $new_w = min($dest_w, $orig_w);
  422. $new_h = min($dest_h, $orig_h);
  423. if ( ! $new_w ) {
  424. $new_w = (int) round( $new_h * $aspect_ratio );
  425. }
  426. if ( ! $new_h ) {
  427. $new_h = (int) round( $new_w / $aspect_ratio );
  428. }
  429. $size_ratio = max($new_w / $orig_w, $new_h / $orig_h);
  430. $crop_w = round($new_w / $size_ratio);
  431. $crop_h = round($new_h / $size_ratio);
  432. if ( ! is_array( $crop ) || count( $crop ) !== 2 ) {
  433. $crop = array( 'center', 'center' );
  434. }
  435. list( $x, $y ) = $crop;
  436. if ( 'left' === $x ) {
  437. $s_x = 0;
  438. } elseif ( 'right' === $x ) {
  439. $s_x = $orig_w - $crop_w;
  440. } else {
  441. $s_x = floor( ( $orig_w - $crop_w ) / 2 );
  442. }
  443. if ( 'top' === $y ) {
  444. $s_y = 0;
  445. } elseif ( 'bottom' === $y ) {
  446. $s_y = $orig_h - $crop_h;
  447. } else {
  448. $s_y = floor( ( $orig_h - $crop_h ) / 2 );
  449. }
  450. } else {
  451. // don't crop, just resize using $dest_w x $dest_h as a maximum bounding box
  452. $crop_w = $orig_w;
  453. $crop_h = $orig_h;
  454. $s_x = 0;
  455. $s_y = 0;
  456. list( $new_w, $new_h ) = wp_constrain_dimensions( $orig_w, $orig_h, $dest_w, $dest_h );
  457. }
  458. // if the resulting image would be the same size or larger we don't want to resize it
  459. if ( $new_w >= $orig_w && $new_h >= $orig_h && $dest_w != $orig_w && $dest_h != $orig_h ) {
  460. return false;
  461. }
  462. // the return array matches the parameters to imagecopyresampled()
  463. // int dst_x, int dst_y, int src_x, int src_y, int dst_w, int dst_h, int src_w, int src_h
  464. return array( 0, 0, (int) $s_x, (int) $s_y, (int) $new_w, (int) $new_h, (int) $crop_w, (int) $crop_h );
  465. }
  466. /**
  467. * Resize an image to make a thumbnail or intermediate size.
  468. *
  469. * The returned array has the file size, the image width, and image height. The
  470. * filter 'image_make_intermediate_size' can be used to hook in and change the
  471. * values of the returned array. The only parameter is the resized file path.
  472. *
  473. * @since 2.5.0
  474. *
  475. * @param string $file File path.
  476. * @param int $width Image width.
  477. * @param int $height Image height.
  478. * @param bool $crop Optional, default is false. Whether to crop image to specified height and width or resize.
  479. * @return bool|array False, if no image was created. Metadata array on success.
  480. */
  481. function image_make_intermediate_size( $file, $width, $height, $crop = false ) {
  482. if ( $width || $height ) {
  483. $editor = wp_get_image_editor( $file );
  484. if ( is_wp_error( $editor ) || is_wp_error( $editor->resize( $width, $height, $crop ) ) )
  485. return false;
  486. $resized_file = $editor->save();
  487. if ( ! is_wp_error( $resized_file ) && $resized_file ) {
  488. unset( $resized_file['path'] );
  489. return $resized_file;
  490. }
  491. }
  492. return false;
  493. }
  494. /**
  495. * Retrieve the image's intermediate size (resized) path, width, and height.
  496. *
  497. * The $size parameter can be an array with the width and height respectively.
  498. * If the size matches the 'sizes' metadata array for width and height, then it
  499. * will be used. If there is no direct match, then the nearest image size larger
  500. * than the specified size will be used. If nothing is found, then the function
  501. * will break out and return false.
  502. *
  503. * The metadata 'sizes' is used for compatible sizes that can be used for the
  504. * parameter $size value.
  505. *
  506. * The url path will be given, when the $size parameter is a string.
  507. *
  508. * If you are passing an array for the $size, you should consider using
  509. * add_image_size() so that a cropped version is generated. It's much more
  510. * efficient than having to find the closest-sized image and then having the
  511. * browser scale down the image.
  512. *
  513. * @since 2.5.0
  514. * @see add_image_size()
  515. *
  516. * @param int $post_id Attachment ID for image.
  517. * @param array|string $size Optional, default is 'thumbnail'. Size of image, either array or string.
  518. * @return bool|array False on failure or array of file path, width, and height on success.
  519. */
  520. function image_get_intermediate_size($post_id, $size='thumbnail') {
  521. if ( !is_array( $imagedata = wp_get_attachment_metadata( $post_id ) ) )
  522. return false;
  523. // get the best one for a specified set of dimensions
  524. if ( is_array($size) && !empty($imagedata['sizes']) ) {
  525. foreach ( $imagedata['sizes'] as $_size => $data ) {
  526. // already cropped to width or height; so use this size
  527. if ( ( $data['width'] == $size[0] && $data['height'] <= $size[1] ) || ( $data['height'] == $size[1] && $data['width'] <= $size[0] ) ) {
  528. $file = $data['file'];
  529. list($width, $height) = image_constrain_size_for_editor( $data['width'], $data['height'], $size );
  530. return compact( 'file', 'width', 'height' );
  531. }
  532. // add to lookup table: area => size
  533. $areas[$data['width'] * $data['height']] = $_size;
  534. }
  535. if ( !$size || !empty($areas) ) {
  536. // find for the smallest image not smaller than the desired size
  537. ksort($areas);
  538. foreach ( $areas as $_size ) {
  539. $data = $imagedata['sizes'][$_size];
  540. if ( $data['width'] >= $size[0] || $data['height'] >= $size[1] ) {
  541. // Skip images with unexpectedly divergent aspect ratios (crops)
  542. // First, we calculate what size the original image would be if constrained to a box the size of the current image in the loop
  543. $maybe_cropped = image_resize_dimensions($imagedata['width'], $imagedata['height'], $data['width'], $data['height'], false );
  544. // If the size doesn't match within one pixel, then it is of a different aspect ratio, so we skip it, unless it's the thumbnail size
  545. if ( 'thumbnail' != $_size && ( !$maybe_cropped || ( $maybe_cropped[4] != $data['width'] && $maybe_cropped[4] + 1 != $data['width'] ) || ( $maybe_cropped[5] != $data['height'] && $maybe_cropped[5] + 1 != $data['height'] ) ) )
  546. continue;
  547. // If we're still here, then we're going to use this size
  548. $file = $data['file'];
  549. list($width, $height) = image_constrain_size_for_editor( $data['width'], $data['height'], $size );
  550. return compact( 'file', 'width', 'height' );
  551. }
  552. }
  553. }
  554. }
  555. if ( is_array($size) || empty($size) || empty($imagedata['sizes'][$size]) )
  556. return false;
  557. $data = $imagedata['sizes'][$size];
  558. // include the full filesystem path of the intermediate file
  559. if ( empty($data['path']) && !empty($data['file']) ) {
  560. $file_url = wp_get_attachment_url($post_id);
  561. $data['path'] = path_join( dirname($imagedata['file']), $data['file'] );
  562. $data['url'] = path_join( dirname($file_url), $data['file'] );
  563. }
  564. return $data;
  565. }
  566. /**
  567. * Get the available image sizes
  568. * @since 3.0.0
  569. * @return array Returns a filtered array of image size strings
  570. */
  571. function get_intermediate_image_sizes() {
  572. global $_wp_additional_image_sizes;
  573. $image_sizes = array('thumbnail', 'medium', 'large'); // Standard sizes
  574. if ( isset( $_wp_additional_image_sizes ) && count( $_wp_additional_image_sizes ) )
  575. $image_sizes = array_merge( $image_sizes, array_keys( $_wp_additional_image_sizes ) );
  576. /**
  577. * Filter the list of intermediate image sizes.
  578. *
  579. * @since 2.5.0
  580. *
  581. * @param array $image_sizes An array of intermediate image sizes. Defaults
  582. * are 'thumbnail', 'medium', 'large'.
  583. */
  584. return apply_filters( 'intermediate_image_sizes', $image_sizes );
  585. }
  586. /**
  587. * Retrieve an image to represent an attachment.
  588. *
  589. * A mime icon for files, thumbnail or intermediate size for images.
  590. *
  591. * @since 2.5.0
  592. *
  593. * @param int $attachment_id Image attachment ID.
  594. * @param string $size Optional, default is 'thumbnail'.
  595. * @param bool $icon Optional, default is false. Whether it is an icon.
  596. * @return bool|array Returns an array (url, width, height), or false, if no image is available.
  597. */
  598. function wp_get_attachment_image_src($attachment_id, $size='thumbnail', $icon = false) {
  599. // get a thumbnail or intermediate image if there is one
  600. if ( $image = image_downsize($attachment_id, $size) )
  601. return $image;
  602. $src = false;
  603. if ( $icon && $src = wp_mime_type_icon($attachment_id) ) {
  604. /** This filter is documented in wp-includes/post.php */
  605. $icon_dir = apply_filters( 'icon_dir', ABSPATH . WPINC . '/images/media' );
  606. $src_file = $icon_dir . '/' . wp_basename($src);
  607. @list($width, $height) = getimagesize($src_file);
  608. }
  609. if ( $src && $width && $height )
  610. return array( $src, $width, $height );
  611. return false;
  612. }
  613. /**
  614. * Get an HTML img element representing an image attachment
  615. *
  616. * While $size will accept an array, it is better to register a size with
  617. * add_image_size() so that a cropped version is generated. It's much more
  618. * efficient than having to find the closest-sized image and then having the
  619. * browser scale down the image.
  620. *
  621. * @since 2.5.0
  622. *
  623. * @see add_image_size()
  624. *
  625. * @param int $attachment_id Image attachment ID.
  626. * @param string|array $size Optional. Default 'thumbnail'.
  627. * @param bool $icon Optional. Whether it is an icon. Default false.
  628. * @param string|array $attr Optional. Attributes for the image markup. Default empty string.
  629. * @return string HTML img element or empty string on failure.
  630. */
  631. function wp_get_attachment_image($attachment_id, $size = 'thumbnail', $icon = false, $attr = '') {
  632. $html = '';
  633. $image = wp_get_attachment_image_src($attachment_id, $size, $icon);
  634. if ( $image ) {
  635. list($src, $width, $height) = $image;
  636. $hwstring = image_hwstring($width, $height);
  637. $size_class = $size;
  638. if ( is_array( $size_class ) ) {
  639. $size_class = join( 'x', $size_class );
  640. }
  641. $attachment = get_post($attachment_id);
  642. $default_attr = array(
  643. 'src' => $src,
  644. 'class' => "attachment-$size_class",
  645. 'alt' => trim(strip_tags( get_post_meta($attachment_id, '_wp_attachment_image_alt', true) )), // Use Alt field first
  646. );
  647. if ( empty($default_attr['alt']) )
  648. $default_attr['alt'] = trim(strip_tags( $attachment->post_excerpt )); // If not, Use the Caption
  649. if ( empty($default_attr['alt']) )
  650. $default_attr['alt'] = trim(strip_tags( $attachment->post_title )); // Finally, use the title
  651. $attr = wp_parse_args($attr, $default_attr);
  652. /**
  653. * Filter the list of attachment image attributes.
  654. *
  655. * @since 2.8.0
  656. *
  657. * @param array $attr Attributes for the image markup.
  658. * @param WP_Post $attachment Image attachment post.
  659. * @param string|array $size Requested size.
  660. */
  661. $attr = apply_filters( 'wp_get_attachment_image_attributes', $attr, $attachment, $size );
  662. $attr = array_map( 'esc_attr', $attr );
  663. $html = rtrim("<img $hwstring");
  664. foreach ( $attr as $name => $value ) {
  665. $html .= " $name=" . '"' . $value . '"';
  666. }
  667. $html .= ' />';
  668. }
  669. return $html;
  670. }
  671. /**
  672. * Adds a 'wp-post-image' class to post thumbnails
  673. * Uses the begin_fetch_post_thumbnail_html and end_fetch_post_thumbnail_html action hooks to
  674. * dynamically add/remove itself so as to only filter post thumbnails
  675. *
  676. * @since 2.9.0
  677. * @param array $attr Attributes including src, class, alt, title
  678. * @return array
  679. */
  680. function _wp_post_thumbnail_class_filter( $attr ) {
  681. $attr['class'] .= ' wp-post-image';
  682. return $attr;
  683. }
  684. /**
  685. * Adds _wp_post_thumbnail_class_filter to the wp_get_attachment_image_attributes filter
  686. *
  687. * @since 2.9.0
  688. */
  689. function _wp_post_thumbnail_class_filter_add( $attr ) {
  690. add_filter( 'wp_get_attachment_image_attributes', '_wp_post_thumbnail_class_filter' );
  691. }
  692. /**
  693. * Removes _wp_post_thumbnail_class_filter from the wp_get_attachment_image_attributes filter
  694. *
  695. * @since 2.9.0
  696. */
  697. function _wp_post_thumbnail_class_filter_remove( $attr ) {
  698. remove_filter( 'wp_get_attachment_image_attributes', '_wp_post_thumbnail_class_filter' );
  699. }
  700. add_shortcode('wp_caption', 'img_caption_shortcode');
  701. add_shortcode('caption', 'img_caption_shortcode');
  702. /**
  703. * The Caption shortcode.
  704. *
  705. * Allows a plugin to replace the content that would otherwise be returned. The
  706. * filter is 'img_caption_shortcode' and passes an empty string, the attr
  707. * parameter and the content parameter values.
  708. *
  709. * The supported attributes for the shortcode are 'id', 'align', 'width', and
  710. * 'caption'.
  711. *
  712. * @since 2.6.0
  713. *
  714. * @param array $attr {
  715. * Attributes of the caption shortcode.
  716. *
  717. * @type string $id ID of the div element for the caption.
  718. * @type string $align Class name that aligns the caption. Default 'alignnone'. Accepts 'alignleft',
  719. * 'aligncenter', alignright', 'alignnone'.
  720. * @type int $width The width of the caption, in pixels.
  721. * @type string $caption The caption text.
  722. * @type string $class Additional class name(s) added to the caption container.
  723. * }
  724. * @param string $content Optional. Shortcode content.
  725. * @return string HTML content to display the caption.
  726. */
  727. function img_caption_shortcode( $attr, $content = null ) {
  728. // New-style shortcode with the caption inside the shortcode with the link and image tags.
  729. if ( ! isset( $attr['caption'] ) ) {
  730. if ( preg_match( '#((?:<a [^>]+>\s*)?<img [^>]+>(?:\s*</a>)?)(.*)#is', $content, $matches ) ) {
  731. $content = $matches[1];
  732. $attr['caption'] = trim( $matches[2] );
  733. }
  734. }
  735. /**
  736. * Filter the default caption shortcode output.
  737. *
  738. * If the filtered output isn't empty, it will be used instead of generating
  739. * the default caption template.
  740. *
  741. * @since 2.6.0
  742. *
  743. * @see img_caption_shortcode()
  744. *
  745. * @param string $output The caption output. Default empty.
  746. * @param array $attr Attributes of the caption shortcode.
  747. * @param string $content The image element, possibly wrapped in a hyperlink.
  748. */
  749. $output = apply_filters( 'img_caption_shortcode', '', $attr, $content );
  750. if ( $output != '' )
  751. return $output;
  752. $atts = shortcode_atts( array(
  753. 'id' => '',
  754. 'align' => 'alignnone',
  755. 'width' => '',
  756. 'caption' => '',
  757. 'class' => '',
  758. ), $attr, 'caption' );
  759. $atts['width'] = (int) $atts['width'];
  760. if ( $atts['width'] < 1 || empty( $atts['caption'] ) )
  761. return $content;
  762. if ( ! empty( $atts['id'] ) )
  763. $atts['id'] = 'id="' . esc_attr( $atts['id'] ) . '" ';
  764. $class = trim( 'wp-caption ' . $atts['align'] . ' ' . $atts['class'] );
  765. if ( current_theme_supports( 'html5', 'caption' ) ) {
  766. return '<figure ' . $atts['id'] . 'style="width: ' . (int) $atts['width'] . 'px;" class="' . esc_attr( $class ) . '">'
  767. . do_shortcode( $content ) . '<figcaption class="wp-caption-text">' . $atts['caption'] . '</figcaption></figure>';
  768. }
  769. $caption_width = 10 + $atts['width'];
  770. /**
  771. * Filter the width of an image's caption.
  772. *
  773. * By default, the caption is 10 pixels greater than the width of the image,
  774. * to prevent post content from running up against a floated image.
  775. *
  776. * @since 3.7.0
  777. *
  778. * @see img_caption_shortcode()
  779. *
  780. * @param int $caption_width Width of the caption in pixels. To remove this inline style,
  781. * return zero.
  782. * @param array $atts Attributes of the caption shortcode.
  783. * @param string $content The image element, possibly wrapped in a hyperlink.
  784. */
  785. $caption_width = apply_filters( 'img_caption_shortcode_width', $caption_width, $atts, $content );
  786. $style = '';
  787. if ( $caption_width )
  788. $style = 'style="width: ' . (int) $caption_width . 'px" ';
  789. return '<div ' . $atts['id'] . $style . 'class="' . esc_attr( $class ) . '">'
  790. . do_shortcode( $content ) . '<p class="wp-caption-text">' . $atts['caption'] . '</p></div>';
  791. }
  792. add_shortcode('gallery', 'gallery_shortcode');
  793. /**
  794. * The Gallery shortcode.
  795. *
  796. * This implements the functionality of the Gallery Shortcode for displaying
  797. * WordPress images on a post.
  798. *
  799. * @since 2.5.0
  800. *
  801. * @param array $attr {
  802. * Attributes of the gallery shortcode.
  803. *
  804. * @type string $order Order of the images in the gallery. Default 'ASC'. Accepts 'ASC', 'DESC'.
  805. * @type string $orderby The field to use when ordering the images. Default 'menu_order ID'.
  806. * Accepts any valid SQL ORDERBY statement.
  807. * @type int $id Post ID.
  808. * @type string $itemtag HTML tag to use for each image in the gallery.
  809. * Default 'dl', or 'figure' when the theme registers HTML5 gallery support.
  810. * @type string $icontag HTML tag to use for each image's icon.
  811. * Default 'dt', or 'div' when the theme registers HTML5 gallery support.
  812. * @type string $captiontag HTML tag to use for each image's caption.
  813. * Default 'dd', or 'figcaption' when the theme registers HTML5 gallery support.
  814. * @type int $columns Number of columns of images to display. Default 3.
  815. * @type string $size Size of the images to display. Default 'thumbnail'.
  816. * @type string $ids A comma-separated list of IDs of attachments to display. Default empty.
  817. * @type string $include A comma-separated list of IDs of attachments to include. Default empty.
  818. * @type string $exclude A comma-separated list of IDs of attachments to exclude. Default empty.
  819. * @type string $link What to link each image to. Default empty (links to the attachment page).
  820. * Accepts 'file', 'none'.
  821. * }
  822. * @return string HTML content to display gallery.
  823. */
  824. function gallery_shortcode( $attr ) {
  825. $post = get_post();
  826. static $instance = 0;
  827. $instance++;
  828. if ( ! empty( $attr['ids'] ) ) {
  829. // 'ids' is explicitly ordered, unless you specify otherwise.
  830. if ( empty( $attr['orderby'] ) ) {
  831. $attr['orderby'] = 'post__in';
  832. }
  833. $attr['include'] = $attr['ids'];
  834. }
  835. /**
  836. * Filter the default gallery shortcode output.
  837. *
  838. * If the filtered output isn't empty, it will be used instead of generating
  839. * the default gallery template.
  840. *
  841. * @since 2.5.0
  842. *
  843. * @see gallery_shortcode()
  844. *
  845. * @param string $output The gallery output. Default empty.
  846. * @param array $attr Attributes of the gallery shortcode.
  847. */
  848. $output = apply_filters( 'post_gallery', '', $attr );
  849. if ( $output != '' ) {
  850. return $output;
  851. }
  852. $html5 = current_theme_supports( 'html5', 'gallery' );
  853. $atts = shortcode_atts( array(
  854. 'order' => 'ASC',
  855. 'orderby' => 'menu_order ID',
  856. 'id' => $post ? $post->ID : 0,
  857. 'itemtag' => $html5 ? 'figure' : 'dl',
  858. 'icontag' => $html5 ? 'div' : 'dt',
  859. 'captiontag' => $html5 ? 'figcaption' : 'dd',
  860. 'columns' => 3,
  861. 'size' => 'thumbnail',
  862. 'include' => '',
  863. 'exclude' => '',
  864. 'link' => ''
  865. ), $attr, 'gallery' );
  866. $id = intval( $atts['id'] );
  867. if ( ! empty( $atts['include'] ) ) {
  868. $_attachments = get_posts( array( 'include' => $atts['include'], 'post_status' => 'inherit', 'post_type' => 'attachment', 'post_mime_type' => 'image', 'order' => $atts['order'], 'orderby' => $atts['orderby'] ) );
  869. $attachments = array();
  870. foreach ( $_attachments as $key => $val ) {
  871. $attachments[$val->ID] = $_attachments[$key];
  872. }
  873. } elseif ( ! empty( $atts['exclude'] ) ) {
  874. $attachments = get_children( array( 'post_parent' => $id, 'exclude' => $atts['exclude'], 'post_status' => 'inherit', 'post_type' => 'attachment', 'post_mime_type' => 'image', 'order' => $atts['order'], 'orderby' => $atts['orderby'] ) );
  875. } else {
  876. $attachments = get_children( array( 'post_parent' => $id, 'post_status' => 'inherit', 'post_type' => 'attachment', 'post_mime_type' => 'image', 'order' => $atts['order'], 'orderby' => $atts['orderby'] ) );
  877. }
  878. if ( empty( $attachments ) ) {
  879. return '';
  880. }
  881. if ( is_feed() ) {
  882. $output = "\n";
  883. foreach ( $attachments as $att_id => $attachment ) {
  884. $output .= wp_get_attachment_link( $att_id, $atts['size'], true ) . "\n";
  885. }
  886. return $output;
  887. }
  888. $itemtag = tag_escape( $atts['itemtag'] );
  889. $captiontag = tag_escape( $atts['captiontag'] );
  890. $icontag = tag_escape( $atts['icontag'] );
  891. $valid_tags = wp_kses_allowed_html( 'post' );
  892. if ( ! isset( $valid_tags[ $itemtag ] ) ) {
  893. $itemtag = 'dl';
  894. }
  895. if ( ! isset( $valid_tags[ $captiontag ] ) ) {
  896. $captiontag = 'dd';
  897. }
  898. if ( ! isset( $valid_tags[ $icontag ] ) ) {
  899. $icontag = 'dt';
  900. }
  901. $columns = intval( $atts['columns'] );
  902. $itemwidth = $columns > 0 ? floor(100/$columns) : 100;
  903. $float = is_rtl() ? 'right' : 'left';
  904. $selector = "gallery-{$instance}";
  905. $gallery_style = '';
  906. /**
  907. * Filter whether to print default gallery styles.
  908. *
  909. * @since 3.1.0
  910. *
  911. * @param bool $print Whether to print default gallery styles.
  912. * Defaults to false if the theme supports HTML5 galleries.
  913. * Otherwise, defaults to true.
  914. */
  915. if ( apply_filters( 'use_default_gallery_style', ! $html5 ) ) {
  916. $gallery_style = "
  917. <style type='text/css'>
  918. #{$selector} {
  919. margin: auto;
  920. }
  921. #{$selector} .gallery-item {
  922. float: {$float};
  923. margin-top: 10px;
  924. text-align: center;
  925. width: {$itemwidth}%;
  926. }
  927. #{$selector} img {
  928. border: 2px solid #cfcfcf;
  929. }
  930. #{$selector} .gallery-caption {
  931. margin-left: 0;
  932. }
  933. /* see gallery_shortcode() in wp-includes/media.php */
  934. </style>\n\t\t";
  935. }
  936. $size_class = sanitize_html_class( $atts['size'] );
  937. $gallery_div = "<div id='$selector' class='gallery galleryid-{$id} gallery-columns-{$columns} gallery-size-{$size_class}'>";
  938. /**
  939. * Filter the default gallery shortcode CSS styles.
  940. *
  941. * @since 2.5.0
  942. *
  943. * @param string $gallery_style Default CSS styles and opening HTML div container
  944. * for the gallery shortcode output.
  945. */
  946. $output = apply_filters( 'gallery_style', $gallery_style . $gallery_div );
  947. $i = 0;
  948. foreach ( $attachments as $id => $attachment ) {
  949. $attr = ( trim( $attachment->post_excerpt ) ) ? array( 'aria-describedby' => "$selector-$id" ) : '';
  950. if ( ! empty( $atts['link'] ) && 'file' === $atts['link'] ) {
  951. $image_output = wp_get_attachment_link( $id, $atts['size'], false, false, false, $attr );
  952. } elseif ( ! empty( $atts['link'] ) && 'none' === $atts['link'] ) {
  953. $image_output = wp_get_attachment_image( $id, $atts['size'], false, $attr );
  954. } else {
  955. $image_output = wp_get_attachment_link( $id, $atts['size'], true, false, false, $attr );
  956. }
  957. $image_meta = wp_get_attachment_metadata( $id );
  958. $orientation = '';
  959. if ( isset( $image_meta['height'], $image_meta['width'] ) ) {
  960. $orientation = ( $image_meta['height'] > $image_meta['width'] ) ? 'portrait' : 'landscape';
  961. }
  962. $output .= "<{$itemtag} class='gallery-item'>";
  963. $output .= "
  964. <{$icontag} class='gallery-icon {$orientation}'>
  965. $image_output
  966. </{$icontag}>";
  967. if ( $captiontag && trim($attachment->post_excerpt) ) {
  968. $output .= "
  969. <{$captiontag} class='wp-caption-text gallery-caption' id='$selector-$id'>
  970. " . wptexturize($attachment->post_excerpt) . "
  971. </{$captiontag}>";
  972. }
  973. $output .= "</{$itemtag}>";
  974. if ( ! $html5 && $columns > 0 && ++$i % $columns == 0 ) {
  975. $output .= '<br style="clear: both" />';
  976. }
  977. }
  978. if ( ! $html5 && $columns > 0 && $i % $columns !== 0 ) {
  979. $output .= "
  980. <br style='clear: both' />";
  981. }
  982. $output .= "
  983. </div>\n";
  984. return $output;
  985. }
  986. /**
  987. * Output the templates used by playlists.
  988. *
  989. * @since 3.9.0
  990. */
  991. function wp_underscore_playlist_templates() {
  992. ?>
  993. <script type="text/html" id="tmpl-wp-playlist-current-item">
  994. <# if ( data.image ) { #>
  995. <img src="{{ data.thumb.src }}"/>
  996. <# } #>
  997. <div class="wp-playlist-caption">
  998. <span class="wp-playlist-item-meta wp-playlist-item-title">&#8220;{{ data.title }}&#8221;</span>
  999. <# if ( data.meta.album ) { #><span class="wp-playlist-item-meta wp-playlist-item-album">{{ data.meta.album }}</span><# } #>
  1000. <# if ( data.meta.artist ) { #><span class="wp-playlist-item-meta wp-playlist-item-artist">{{ data.meta.artist }}</span><# } #>
  1001. </div>
  1002. </script>
  1003. <script type="text/html" id="tmpl-wp-playlist-item">
  1004. <div class="wp-playlist-item">
  1005. <a class="wp-playlist-caption" href="{{ data.src }}">
  1006. {{ data.index ? ( data.index + '. ' ) : '' }}
  1007. <# if ( data.caption ) { #>
  1008. {{ data.caption }}
  1009. <# } else { #>
  1010. <span class="wp-playlist-item-title">&#8220;{{{ data.title }}}&#8221;</span>
  1011. <# if ( data.artists && data.meta.artist ) { #>
  1012. <span class="wp-playlist-item-artist"> &mdash; {{ data.meta.artist }}</span>
  1013. <# } #>
  1014. <# } #>
  1015. </a>
  1016. <# if ( data.meta.length_formatted ) { #>
  1017. <div class="wp-playlist-item-length">{{ data.meta.length_formatted }}</div>
  1018. <# } #>
  1019. </div>
  1020. </script>
  1021. <?php
  1022. }
  1023. /**
  1024. * Output and enqueue default scripts and styles for playlists.
  1025. *
  1026. * @since 3.9.0
  1027. *
  1028. * @param string $type Type of playlist. Accepts 'audio' or 'video'.
  1029. */
  1030. function wp_playlist_scripts( $type ) {
  1031. wp_enqueue_style( 'wp-mediaelement' );
  1032. wp_enqueue_script( 'wp-playlist' );
  1033. ?>
  1034. <!--[if lt IE 9]><script>document.createElement('<?php echo esc_js( $type ) ?>');</script><![endif]-->
  1035. <?php
  1036. add_action( 'wp_footer', 'wp_underscore_playlist_templates', 0 );
  1037. add_action( 'admin_footer', 'wp_underscore_playlist_templates', 0 );
  1038. }
  1039. add_action( 'wp_playlist_scripts', 'wp_playlist_scripts' );
  1040. /**
  1041. * The playlist shortcode.
  1042. *
  1043. * This implements the functionality of the playlist shortcode for displaying
  1044. * a collection of WordPress audio or video files in a post.
  1045. *
  1046. * @since 3.9.0
  1047. *
  1048. * @param array $attr {
  1049. * Array of default playlist attributes.
  1050. *
  1051. * @type string $type Type of playlist to display. Accepts 'audio' or 'video'. Default 'audio'.
  1052. * @type string $order Designates ascending or descending order of items in the playlist.
  1053. * Accepts 'ASC', 'DESC'. Default 'ASC'.
  1054. * @type string $orderby Any column, or columns, to sort the playlist. If $ids are
  1055. * passed, this defaults to the order of the $ids array ('post__in').
  1056. * Otherwise default is 'menu_order ID'.
  1057. * @type int $id If an explicit $ids array is not present, this parameter
  1058. * will determine which attachments are used for the playlist.
  1059. * Default is the current post ID.
  1060. * @type array $ids Create a playlist out of these explicit attachment IDs. If empty,
  1061. * a playlist will be created from all $type attachments of $id.
  1062. * Default empty.
  1063. * @type array $exclude List of specific attachment IDs to exclude from the playlist. Default empty.
  1064. * @type string $style Playlist style to use. Accepts 'light' or 'dark'. Default 'light'.
  1065. * @type bool $tracklist Whether to show or hide the playlist. Default true.
  1066. * @type bool $tracknumbers Whether to show or hide the numbers next to entries in the playlist. Default true.
  1067. * @type bool $images Show or hide the video or audio thumbnail (Featured Image/post
  1068. * thumbnail). Default true.
  1069. * @type bool $artists Whether to show or hide artist name in the playlist. Default true.
  1070. * }
  1071. *
  1072. * @return string Playlist output. Empty string if the passed type is unsupported.
  1073. */
  1074. function wp_playlist_shortcode( $attr ) {
  1075. global $content_width;
  1076. $post = get_post();
  1077. static $instance = 0;
  1078. $instance++;
  1079. if ( ! empty( $attr['ids'] ) ) {
  1080. // 'ids' is explicitly ordered, unless you specify otherwise.
  1081. if ( empty( $attr['orderby'] ) ) {
  1082. $attr['orderby'] = 'post__in';
  1083. }
  1084. $attr['include'] = $attr['ids'];
  1085. }
  1086. /**
  1087. * Filter the playlist output.
  1088. *
  1089. * Passing a non-empty value to the filter will short-circuit generation
  1090. * of the default playlist output, returning the passed value instead.
  1091. *
  1092. * @since 3.9.0
  1093. *
  1094. * @param string $output Playlist output. Default empty.
  1095. * @param array $attr An array of shortcode attributes.
  1096. */
  1097. $output = apply_filters( 'post_playlist', '', $attr );
  1098. if ( $output != '' ) {
  1099. return $output;
  1100. }
  1101. $atts = shortcode_atts( array(
  1102. 'type' => 'audio',
  1103. 'order' => 'ASC',
  1104. 'orderby' => 'menu_order ID',
  1105. 'id' => $post ? $post->ID : 0,
  1106. 'include' => '',
  1107. 'exclude' => '',
  1108. 'style' => 'light',
  1109. 'tracklist' => true,
  1110. 'tracknumbers' => true,
  1111. 'images' => true,
  1112. 'artists' => true
  1113. ), $attr, 'playlist' );
  1114. $id = intval( $atts['id'] );
  1115. if ( $atts['type'] !== 'audio' ) {
  1116. $atts['type'] = 'video';
  1117. }
  1118. $args = array(
  1119. 'post_status' => 'inherit',
  1120. 'post_type' => 'attachment',
  1121. 'post_mime_type' => $atts['type'],
  1122. 'order' => $atts['order'],
  1123. 'orderby' => $atts['orderby']
  1124. );
  1125. if ( ! empty( $atts['include'] ) ) {
  1126. $args['include'] = $atts['include'];
  1127. $_attachments = get_posts( $args );
  1128. $attachments = array();
  1129. foreach ( $_attachments as $key => $val ) {
  1130. $attachments[$val->ID] = $_attachments[$key];
  1131. }
  1132. } elseif ( ! empty( $atts['exclude'] ) ) {
  1133. $args['post_parent'] = $id;
  1134. $args['exclude'] = $atts['exclude'];
  1135. $attachments = get_children( $args );
  1136. } else {
  1137. $args['post_parent'] = $id;
  1138. $attachments = get_children( $args );
  1139. }
  1140. if ( empty( $attachments ) ) {
  1141. return '';
  1142. }
  1143. if ( is_feed() ) {
  1144. $output = "\n";
  1145. foreach ( $attachments as $att_id => $attachment ) {
  1146. $output .= wp_get_attachment_link( $att_id ) . "\n";
  1147. }
  1148. return $output;
  1149. }
  1150. $outer = 22; // default padding and border of wrapper
  1151. $default_width = 640;
  1152. $default_height = 360;
  1153. $theme_width = empty( $content_width ) ? $default_width : ( $content_width - $outer );
  1154. $theme_height = empty( $content_width ) ? $default_height : round( ( $default_height * $theme_width ) / $default_width );
  1155. $data = array(
  1156. 'type' => $atts['type'],
  1157. // don't pass strings to JSON, will be truthy in JS
  1158. 'tracklist' => wp_validate_boolean( $atts['tracklist'] ),
  1159. 'tracknumbers' => wp_validate_boolean( $atts['tracknumbers'] ),
  1160. 'images' => wp_validate_boolean( $atts['images'] ),
  1161. 'artists' => wp_validate_boolean( $atts['artists'] ),
  1162. );
  1163. $tracks = array();
  1164. foreach ( $attachments as $attachment ) {
  1165. $url = wp_get_attachment_url( $attachment->ID );
  1166. $ftype = wp_check_filetype( $url, wp_get_mime_types() );
  1167. $track = array(
  1168. 'src' => $url,
  1169. 'type' => $ftype['type'],
  1170. 'title' => $attachment->post_title,
  1171. 'caption' => $attachment->post_excerpt,
  1172. 'description' => $attachment->post_content
  1173. );
  1174. $track['meta'] = array();
  1175. $meta = wp_get_attachment_metadata( $attachment->ID );
  1176. if ( ! empty( $meta ) ) {
  1177. foreach ( wp_get_attachment_id3_keys( $attachment ) as $key => $label ) {
  1178. if ( ! empty( $meta[ $key ] ) ) {
  1179. $track['meta'][ $key ] = $meta[ $key ];
  1180. }
  1181. }
  1182. if ( 'video' === $atts['type'] ) {
  1183. if ( ! empty( $meta['width'] ) && ! empty( $meta['height'] ) ) {
  1184. $width = $meta['width'];
  1185. $height = $meta['height'];
  1186. $theme_height = round( ( $height * $theme_width ) / $width );
  1187. } else {
  1188. $width = $default_width;
  1189. $height = $default_height;
  1190. }
  1191. $track['dimensions'] = array(
  1192. 'original' => compact( 'width', 'height' ),
  1193. 'resized' => array(
  1194. 'width' => $theme_width,
  1195. 'height' => $theme_height
  1196. )
  1197. );
  1198. }
  1199. }
  1200. if ( $atts['images'] ) {
  1201. $thumb_id = get_post_thumbnail_id( $attachment->ID );
  1202. if ( ! empty( $thumb_id ) ) {
  1203. list( $src, $width, $height ) = wp_get_attachment_image_src( $thumb_id, 'full' );
  1204. $track['image'] = compact( 'src', 'width', 'height' );
  1205. list( $src, $width, $height ) = wp_get_attachment_image_src( $thumb_id, 'thumbnail' );
  1206. $track['thumb'] = compact( 'src', 'width', 'height' );
  1207. } else {
  1208. $src = wp_mime_type_icon( $attachment->ID );
  1209. $width = 48;
  1210. $height = 64;
  1211. $track['image'] = compact( 'src', 'width', 'height' );
  1212. $track['thumb'] = compact( 'src', 'width', 'height' );
  1213. }
  1214. }
  1215. $tracks[] = $track;
  1216. }
  1217. $data['tracks'] = $tracks;
  1218. $safe_type = esc_attr( $atts['type'] );
  1219. $safe_style = esc_attr( $atts['style'] );
  1220. ob_start();
  1221. if ( 1 === $instance ) {
  1222. /**
  1223. * Print and enqueue playlist scripts, styles, and JavaScript templates.
  1224. *
  1225. * @since 3.9.0
  1226. *
  1227. * @param string $type Type of playlist. Possible values are 'audio' or 'video'.
  1228. * @param string $style The 'theme' for the playlist. Core provides 'light' and 'dark'.
  1229. */
  1230. do_action( 'wp_playlist_scripts', $atts['type'], $atts['style'] );
  1231. } ?>
  1232. <div class="wp-playlist wp-<?php echo $safe_type ?>-playlist wp-playlist-<?php echo $safe_style ?>">
  1233. <?php if ( 'audio' === $atts['type'] ): ?>
  1234. <div class="wp-playlist-current-item"></div>
  1235. <?php endif ?>
  1236. <<?php echo $safe_type ?> controls="controls" preload="none" width="<?php
  1237. echo (int

Large files files are truncated, but you can click here to view the full file