[ Index ]

WordPress Cross Reference

title

Body

[close]

/wp-includes/ -> media.php (source)

   1  <?php
   2  /**
   3   * WordPress API for media display.
   4   *
   5   * @package WordPress
   6   * @subpackage Media
   7   */
   8  
   9  /**
  10   * Scale down the default size of an image.
  11   *
  12   * This is so that the image is a better fit for the editor and theme.
  13   *
  14   * The $size parameter accepts either an array or a string. The supported string
  15   * values are 'thumb' or 'thumbnail' for the given thumbnail size or defaults at
  16   * 128 width and 96 height in pixels. Also supported for the string value is
  17   * 'medium' and 'full'. The 'full' isn't actually supported, but any value other
  18   * than the supported will result in the content_width size or 500 if that is
  19   * not set.
  20   *
  21   * Finally, there is a filter named 'editor_max_image_size', that will be called
  22   * on the calculated array for width and height, respectively. The second
  23   * parameter will be the value that was in the $size parameter. The returned
  24   * type for the hook is an array with the width as the first element and the
  25   * height as the second element.
  26   *
  27   * @since 2.5.0
  28   * @uses wp_constrain_dimensions() This function passes the widths and the heights.
  29   *
  30   * @param int $width Width of the image
  31   * @param int $height Height of the image
  32   * @param string|array $size Size of what the result image should be.
  33   * @param context Could be 'display' (like in a theme) or 'edit' (like inserting into an editor)
  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  
  39      if ( ! $context )
  40          $context = is_admin() ? 'edit' : 'display';
  41  
  42      if ( is_array($size) ) {
  43          $max_width = $size[0];
  44          $max_height = $size[1];
  45      }
  46      elseif ( $size == 'thumb' || $size == 'thumbnail' ) {
  47          $max_width = intval(get_option('thumbnail_size_w'));
  48          $max_height = intval(get_option('thumbnail_size_h'));
  49          // last chance thumbnail size defaults
  50          if ( !$max_width && !$max_height ) {
  51              $max_width = 128;
  52              $max_height = 96;
  53          }
  54      }
  55      elseif ( $size == 'medium' ) {
  56          $max_width = intval(get_option('medium_size_w'));
  57          $max_height = intval(get_option('medium_size_h'));
  58          // if no width is set, default to the theme content width if available
  59      }
  60      elseif ( $size == 'large' ) {
  61          // We're inserting a large size image into the editor. If it's a really
  62          // big image we'll scale it down to fit reasonably within the editor
  63          // itself, and within the theme's content width if it's known. The user
  64          // can resize it in the editor if they wish.
  65          $max_width = intval(get_option('large_size_w'));
  66          $max_height = intval(get_option('large_size_h'));
  67          if ( intval($content_width) > 0 )
  68              $max_width = min( intval($content_width), $max_width );
  69      } elseif ( isset( $_wp_additional_image_sizes ) && count( $_wp_additional_image_sizes ) && in_array( $size, array_keys( $_wp_additional_image_sizes ) ) ) {
  70          $max_width = intval( $_wp_additional_image_sizes[$size]['width'] );
  71          $max_height = intval( $_wp_additional_image_sizes[$size]['height'] );
  72          if ( intval($content_width) > 0 && 'edit' == $context ) // Only in admin. Assume that theme authors know what they're doing.
  73              $max_width = min( intval($content_width), $max_width );
  74      }
  75      // $size == 'full' has no constraint
  76      else {
  77          $max_width = $width;
  78          $max_height = $height;
  79      }
  80  
  81      list( $max_width, $max_height ) = apply_filters( 'editor_max_image_size', array( $max_width, $max_height ), $size, $context );
  82  
  83      return wp_constrain_dimensions( $width, $height, $max_width, $max_height );
  84  }
  85  
  86  /**
  87   * Retrieve width and height attributes using given width and height values.
  88   *
  89   * Both attributes are required in the sense that both parameters must have a
  90   * value, but are optional in that if you set them to false or null, then they
  91   * will not be added to the returned string.
  92   *
  93   * You can set the value using a string, but it will only take numeric values.
  94   * If you wish to put 'px' after the numbers, then it will be stripped out of
  95   * the return.
  96   *
  97   * @since 2.5.0
  98   *
  99   * @param int|string $width Optional. Width attribute value.
 100   * @param int|string $height Optional. Height attribute value.
 101   * @return string HTML attributes for width and, or height.
 102   */
 103  function image_hwstring($width, $height) {
 104      $out = '';
 105      if ($width)
 106          $out .= 'width="'.intval($width).'" ';
 107      if ($height)
 108          $out .= 'height="'.intval($height).'" ';
 109      return $out;
 110  }
 111  
 112  /**
 113   * Scale an image to fit a particular size (such as 'thumb' or 'medium').
 114   *
 115   * Array with image url, width, height, and whether is intermediate size, in
 116   * that order is returned on success is returned. $is_intermediate is true if
 117   * $url is a resized image, false if it is the original.
 118   *
 119   * The URL might be the original image, or it might be a resized version. This
 120   * function won't create a new resized copy, it will just return an already
 121   * resized one if it exists.
 122   *
 123   * A plugin may use the 'image_downsize' filter to hook into and offer image
 124   * resizing services for images. The hook must return an array with the same
 125   * elements that are returned in the function. The first element being the URL
 126   * to the new image that was resized.
 127   *
 128   * @since 2.5.0
 129   * @uses apply_filters() Calls 'image_downsize' on $id and $size to provide
 130   *        resize services.
 131   *
 132   * @param int $id Attachment ID for image.
 133   * @param array|string $size Optional, default is 'medium'. Size of image, either array or string.
 134   * @return bool|array False on failure, array on success.
 135   */
 136  function image_downsize($id, $size = 'medium') {
 137  
 138      if ( !wp_attachment_is_image($id) )
 139          return false;
 140  
 141      // plugins can use this to provide resize services
 142      if ( $out = apply_filters( 'image_downsize', false, $id, $size ) )
 143          return $out;
 144  
 145      $img_url = wp_get_attachment_url($id);
 146      $meta = wp_get_attachment_metadata($id);
 147      $width = $height = 0;
 148      $is_intermediate = false;
 149      $img_url_basename = wp_basename($img_url);
 150  
 151      // try for a new style intermediate size
 152      if ( $intermediate = image_get_intermediate_size($id, $size) ) {
 153          $img_url = str_replace($img_url_basename, $intermediate['file'], $img_url);
 154          $width = $intermediate['width'];
 155          $height = $intermediate['height'];
 156          $is_intermediate = true;
 157      }
 158      elseif ( $size == 'thumbnail' ) {
 159          // fall back to the old thumbnail
 160          if ( ($thumb_file = wp_get_attachment_thumb_file($id)) && $info = getimagesize($thumb_file) ) {
 161              $img_url = str_replace($img_url_basename, wp_basename($thumb_file), $img_url);
 162              $width = $info[0];
 163              $height = $info[1];
 164              $is_intermediate = true;
 165          }
 166      }
 167      if ( !$width && !$height && isset( $meta['width'], $meta['height'] ) ) {
 168          // any other type: use the real image
 169          $width = $meta['width'];
 170          $height = $meta['height'];
 171      }
 172  
 173      if ( $img_url) {
 174          // we have the actual image size, but might need to further constrain it if content_width is narrower
 175          list( $width, $height ) = image_constrain_size_for_editor( $width, $height, $size );
 176  
 177          return array( $img_url, $width, $height, $is_intermediate );
 178      }
 179      return false;
 180  
 181  }
 182  
 183  /**
 184   * Registers a new image size
 185   *
 186   * @since 2.9.0
 187   */
 188  function add_image_size( $name, $width = 0, $height = 0, $crop = false ) {
 189      global $_wp_additional_image_sizes;
 190      $_wp_additional_image_sizes[$name] = array( 'width' => absint( $width ), 'height' => absint( $height ), 'crop' => (bool) $crop );
 191  }
 192  
 193  /**
 194   * Registers an image size for the post thumbnail
 195   *
 196   * @since 2.9.0
 197   */
 198  function set_post_thumbnail_size( $width = 0, $height = 0, $crop = false ) {
 199      add_image_size( 'post-thumbnail', $width, $height, $crop );
 200  }
 201  
 202  /**
 203   * An <img src /> tag for an image attachment, scaling it down if requested.
 204   *
 205   * The filter 'get_image_tag_class' allows for changing the class name for the
 206   * image without having to use regular expressions on the HTML content. The
 207   * parameters are: what WordPress will use for the class, the Attachment ID,
 208   * image align value, and the size the image should be.
 209   *
 210   * The second filter 'get_image_tag' has the HTML content, which can then be
 211   * further manipulated by a plugin to change all attribute values and even HTML
 212   * content.
 213   *
 214   * @since 2.5.0
 215   *
 216   * @uses apply_filters() The 'get_image_tag_class' filter is the IMG element
 217   *        class attribute.
 218   * @uses apply_filters() The 'get_image_tag' filter is the full IMG element with
 219   *        all attributes.
 220   *
 221   * @param int $id Attachment ID.
 222   * @param string $alt Image Description for the alt attribute.
 223   * @param string $title Image Description for the title attribute.
 224   * @param string $align Part of the class name for aligning the image.
 225   * @param string $size Optional. Default is 'medium'.
 226   * @return string HTML IMG element for given image attachment
 227   */
 228  function get_image_tag($id, $alt, $title, $align, $size='medium') {
 229  
 230      list( $img_src, $width, $height ) = image_downsize($id, $size);
 231      $hwstring = image_hwstring($width, $height);
 232  
 233      $title = $title ? 'title="' . esc_attr( $title ) . '" ' : '';
 234  
 235      $class = 'align' . esc_attr($align) .' size-' . esc_attr($size) . ' wp-image-' . $id;
 236      $class = apply_filters('get_image_tag_class', $class, $id, $align, $size);
 237  
 238      $html = '<img src="' . esc_attr($img_src) . '" alt="' . esc_attr($alt) . '" ' . $title . $hwstring . 'class="' . $class . '" />';
 239  
 240      $html = apply_filters( 'get_image_tag', $html, $id, $alt, $title, $align, $size );
 241  
 242      return $html;
 243  }
 244  
 245  /**
 246   * Calculates the new dimensions for a downsampled image.
 247   *
 248   * If either width or height are empty, no constraint is applied on
 249   * that dimension.
 250   *
 251   * @since 2.5.0
 252   *
 253   * @param int $current_width Current width of the image.
 254   * @param int $current_height Current height of the image.
 255   * @param int $max_width Optional. Maximum wanted width.
 256   * @param int $max_height Optional. Maximum wanted height.
 257   * @return array First item is the width, the second item is the height.
 258   */
 259  function wp_constrain_dimensions( $current_width, $current_height, $max_width=0, $max_height=0 ) {
 260      if ( !$max_width and !$max_height )
 261          return array( $current_width, $current_height );
 262  
 263      $width_ratio = $height_ratio = 1.0;
 264      $did_width = $did_height = false;
 265  
 266      if ( $max_width > 0 && $current_width > 0 && $current_width > $max_width ) {
 267          $width_ratio = $max_width / $current_width;
 268          $did_width = true;
 269      }
 270  
 271      if ( $max_height > 0 && $current_height > 0 && $current_height > $max_height ) {
 272          $height_ratio = $max_height / $current_height;
 273          $did_height = true;
 274      }
 275  
 276      // Calculate the larger/smaller ratios
 277      $smaller_ratio = min( $width_ratio, $height_ratio );
 278      $larger_ratio  = max( $width_ratio, $height_ratio );
 279  
 280      if ( intval( $current_width * $larger_ratio ) > $max_width || intval( $current_height * $larger_ratio ) > $max_height )
 281           // The larger ratio is too big. It would result in an overflow.
 282          $ratio = $smaller_ratio;
 283      else
 284          // The larger ratio fits, and is likely to be a more "snug" fit.
 285          $ratio = $larger_ratio;
 286  
 287      // Very small dimensions may result in 0, 1 should be the minimum.
 288      $w = max ( 1, intval( $current_width  * $ratio ) );
 289      $h = max ( 1, intval( $current_height * $ratio ) );
 290  
 291      // Sometimes, due to rounding, we'll end up with a result like this: 465x700 in a 177x177 box is 117x176... a pixel short
 292      // 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.
 293      // Thus we look for dimensions that are one pixel shy of the max value and bump them up
 294      if ( $did_width && $w == $max_width - 1 )
 295          $w = $max_width; // Round it up
 296      if ( $did_height && $h == $max_height - 1 )
 297          $h = $max_height; // Round it up
 298  
 299      return array( $w, $h );
 300  }
 301  
 302  /**
 303   * Retrieve calculated resized dimensions for use in WP_Image_Editor.
 304   *
 305   * Calculate dimensions and coordinates for a resized image that fits within a
 306   * specified width and height. If $crop is true, the largest matching central
 307   * portion of the image will be cropped out and resized to the required size.
 308   *
 309   * @since 2.5.0
 310   * @uses apply_filters() Calls 'image_resize_dimensions' on $orig_w, $orig_h, $dest_w, $dest_h and
 311   *        $crop to provide custom resize dimensions.
 312   *
 313   * @param int $orig_w Original width.
 314   * @param int $orig_h Original height.
 315   * @param int $dest_w New width.
 316   * @param int $dest_h New height.
 317   * @param bool $crop Optional, default is false. Whether to crop image or resize.
 318   * @return bool|array False on failure. Returned array matches parameters for imagecopyresampled() PHP function.
 319   */
 320  function image_resize_dimensions($orig_w, $orig_h, $dest_w, $dest_h, $crop = false) {
 321  
 322      if ($orig_w <= 0 || $orig_h <= 0)
 323          return false;
 324      // at least one of dest_w or dest_h must be specific
 325      if ($dest_w <= 0 && $dest_h <= 0)
 326          return false;
 327  
 328      // plugins can use this to provide custom resize dimensions
 329      $output = apply_filters( 'image_resize_dimensions', null, $orig_w, $orig_h, $dest_w, $dest_h, $crop );
 330      if ( null !== $output )
 331          return $output;
 332  
 333      if ( $crop ) {
 334          // crop the largest possible portion of the original image that we can size to $dest_w x $dest_h
 335          $aspect_ratio = $orig_w / $orig_h;
 336          $new_w = min($dest_w, $orig_w);
 337          $new_h = min($dest_h, $orig_h);
 338  
 339          if ( !$new_w ) {
 340              $new_w = intval($new_h * $aspect_ratio);
 341          }
 342  
 343          if ( !$new_h ) {
 344              $new_h = intval($new_w / $aspect_ratio);
 345          }
 346  
 347          $size_ratio = max($new_w / $orig_w, $new_h / $orig_h);
 348  
 349          $crop_w = round($new_w / $size_ratio);
 350          $crop_h = round($new_h / $size_ratio);
 351  
 352          $s_x = floor( ($orig_w - $crop_w) / 2 );
 353          $s_y = floor( ($orig_h - $crop_h) / 2 );
 354      } else {
 355          // don't crop, just resize using $dest_w x $dest_h as a maximum bounding box
 356          $crop_w = $orig_w;
 357          $crop_h = $orig_h;
 358  
 359          $s_x = 0;
 360          $s_y = 0;
 361  
 362          list( $new_w, $new_h ) = wp_constrain_dimensions( $orig_w, $orig_h, $dest_w, $dest_h );
 363      }
 364  
 365      // if the resulting image would be the same size or larger we don't want to resize it
 366      if ( $new_w >= $orig_w && $new_h >= $orig_h )
 367          return false;
 368  
 369      // the return array matches the parameters to imagecopyresampled()
 370      // int dst_x, int dst_y, int src_x, int src_y, int dst_w, int dst_h, int src_w, int src_h
 371      return array( 0, 0, (int) $s_x, (int) $s_y, (int) $new_w, (int) $new_h, (int) $crop_w, (int) $crop_h );
 372  
 373  }
 374  
 375  /**
 376   * Resize an image to make a thumbnail or intermediate size.
 377   *
 378   * The returned array has the file size, the image width, and image height. The
 379   * filter 'image_make_intermediate_size' can be used to hook in and change the
 380   * values of the returned array. The only parameter is the resized file path.
 381   *
 382   * @since 2.5.0
 383   *
 384   * @param string $file File path.
 385   * @param int $width Image width.
 386   * @param int $height Image height.
 387   * @param bool $crop Optional, default is false. Whether to crop image to specified height and width or resize.
 388   * @return bool|array False, if no image was created. Metadata array on success.
 389   */
 390  function image_make_intermediate_size( $file, $width, $height, $crop = false ) {
 391      if ( $width || $height ) {
 392          $editor = wp_get_image_editor( $file );
 393  
 394          if ( is_wp_error( $editor ) || is_wp_error( $editor->resize( $width, $height, $crop ) ) )
 395              return false;
 396  
 397          $resized_file = $editor->save();
 398  
 399          if ( ! is_wp_error( $resized_file ) && $resized_file ) {
 400              unset( $resized_file['path'] );
 401              return $resized_file;
 402          }
 403      }
 404      return false;
 405  }
 406  
 407  /**
 408   * Retrieve the image's intermediate size (resized) path, width, and height.
 409   *
 410   * The $size parameter can be an array with the width and height respectively.
 411   * If the size matches the 'sizes' metadata array for width and height, then it
 412   * will be used. If there is no direct match, then the nearest image size larger
 413   * than the specified size will be used. If nothing is found, then the function
 414   * will break out and return false.
 415   *
 416   * The metadata 'sizes' is used for compatible sizes that can be used for the
 417   * parameter $size value.
 418   *
 419   * The url path will be given, when the $size parameter is a string.
 420   *
 421   * If you are passing an array for the $size, you should consider using
 422   * add_image_size() so that a cropped version is generated. It's much more
 423   * efficient than having to find the closest-sized image and then having the
 424   * browser scale down the image.
 425   *
 426   * @since 2.5.0
 427   * @see add_image_size()
 428   *
 429   * @param int $post_id Attachment ID for image.
 430   * @param array|string $size Optional, default is 'thumbnail'. Size of image, either array or string.
 431   * @return bool|array False on failure or array of file path, width, and height on success.
 432   */
 433  function image_get_intermediate_size($post_id, $size='thumbnail') {
 434      if ( !is_array( $imagedata = wp_get_attachment_metadata( $post_id ) ) )
 435          return false;
 436  
 437      // get the best one for a specified set of dimensions
 438      if ( is_array($size) && !empty($imagedata['sizes']) ) {
 439          foreach ( $imagedata['sizes'] as $_size => $data ) {
 440              // already cropped to width or height; so use this size
 441              if ( ( $data['width'] == $size[0] && $data['height'] <= $size[1] ) || ( $data['height'] == $size[1] && $data['width'] <= $size[0] ) ) {
 442                  $file = $data['file'];
 443                  list($width, $height) = image_constrain_size_for_editor( $data['width'], $data['height'], $size );
 444                  return compact( 'file', 'width', 'height' );
 445              }
 446              // add to lookup table: area => size
 447              $areas[$data['width'] * $data['height']] = $_size;
 448          }
 449          if ( !$size || !empty($areas) ) {
 450              // find for the smallest image not smaller than the desired size
 451              ksort($areas);
 452              foreach ( $areas as $_size ) {
 453                  $data = $imagedata['sizes'][$_size];
 454                  if ( $data['width'] >= $size[0] || $data['height'] >= $size[1] ) {
 455                      // Skip images with unexpectedly divergent aspect ratios (crops)
 456                      // First, we calculate what size the original image would be if constrained to a box the size of the current image in the loop
 457                      $maybe_cropped = image_resize_dimensions($imagedata['width'], $imagedata['height'], $data['width'], $data['height'], false );
 458                      // 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
 459                      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'] ) ) )
 460                          continue;
 461                      // If we're still here, then we're going to use this size
 462                      $file = $data['file'];
 463                      list($width, $height) = image_constrain_size_for_editor( $data['width'], $data['height'], $size );
 464                      return compact( 'file', 'width', 'height' );
 465                  }
 466              }
 467          }
 468      }
 469  
 470      if ( is_array($size) || empty($size) || empty($imagedata['sizes'][$size]) )
 471          return false;
 472  
 473      $data = $imagedata['sizes'][$size];
 474      // include the full filesystem path of the intermediate file
 475      if ( empty($data['path']) && !empty($data['file']) ) {
 476          $file_url = wp_get_attachment_url($post_id);
 477          $data['path'] = path_join( dirname($imagedata['file']), $data['file'] );
 478          $data['url'] = path_join( dirname($file_url), $data['file'] );
 479      }
 480      return $data;
 481  }
 482  
 483  /**
 484   * Get the available image sizes
 485   * @since 3.0.0
 486   * @return array Returns a filtered array of image size strings
 487   */
 488  function get_intermediate_image_sizes() {
 489      global $_wp_additional_image_sizes;
 490      $image_sizes = array('thumbnail', 'medium', 'large'); // Standard sizes
 491      if ( isset( $_wp_additional_image_sizes ) && count( $_wp_additional_image_sizes ) )
 492          $image_sizes = array_merge( $image_sizes, array_keys( $_wp_additional_image_sizes ) );
 493  
 494      return apply_filters( 'intermediate_image_sizes', $image_sizes );
 495  }
 496  
 497  /**
 498   * Retrieve an image to represent an attachment.
 499   *
 500   * A mime icon for files, thumbnail or intermediate size for images.
 501   *
 502   * @since 2.5.0
 503   *
 504   * @param int $attachment_id Image attachment ID.
 505   * @param string $size Optional, default is 'thumbnail'.
 506   * @param bool $icon Optional, default is false. Whether it is an icon.
 507   * @return bool|array Returns an array (url, width, height), or false, if no image is available.
 508   */
 509  function wp_get_attachment_image_src($attachment_id, $size='thumbnail', $icon = false) {
 510  
 511      // get a thumbnail or intermediate image if there is one
 512      if ( $image = image_downsize($attachment_id, $size) )
 513          return $image;
 514  
 515      $src = false;
 516  
 517      if ( $icon && $src = wp_mime_type_icon($attachment_id) ) {
 518          $icon_dir = apply_filters( 'icon_dir', ABSPATH . WPINC . '/images/crystal' );
 519          $src_file = $icon_dir . '/' . wp_basename($src);
 520          @list($width, $height) = getimagesize($src_file);
 521      }
 522      if ( $src && $width && $height )
 523          return array( $src, $width, $height );
 524      return false;
 525  }
 526  
 527  /**
 528   * Get an HTML img element representing an image attachment
 529   *
 530   * While $size will accept an array, it is better to register a size with
 531   * add_image_size() so that a cropped version is generated. It's much more
 532   * efficient than having to find the closest-sized image and then having the
 533   * browser scale down the image.
 534   *
 535   * @see add_image_size()
 536   * @uses apply_filters() Calls 'wp_get_attachment_image_attributes' hook on attributes array
 537   * @uses wp_get_attachment_image_src() Gets attachment file URL and dimensions
 538   * @since 2.5.0
 539   *
 540   * @param int $attachment_id Image attachment ID.
 541   * @param string $size Optional, default is 'thumbnail'.
 542   * @param bool $icon Optional, default is false. Whether it is an icon.
 543   * @param mixed $attr Optional, attributes for the image markup.
 544   * @return string HTML img element or empty string on failure.
 545   */
 546  function wp_get_attachment_image($attachment_id, $size = 'thumbnail', $icon = false, $attr = '') {
 547  
 548      $html = '';
 549      $image = wp_get_attachment_image_src($attachment_id, $size, $icon);
 550      if ( $image ) {
 551          list($src, $width, $height) = $image;
 552          $hwstring = image_hwstring($width, $height);
 553          if ( is_array($size) )
 554              $size = join('x', $size);
 555          $attachment = get_post($attachment_id);
 556          $default_attr = array(
 557              'src'    => $src,
 558              'class'    => "attachment-$size",
 559              'alt'    => trim(strip_tags( get_post_meta($attachment_id, '_wp_attachment_image_alt', true) )), // Use Alt field first
 560          );
 561          if ( empty($default_attr['alt']) )
 562              $default_attr['alt'] = trim(strip_tags( $attachment->post_excerpt )); // If not, Use the Caption
 563          if ( empty($default_attr['alt']) )
 564              $default_attr['alt'] = trim(strip_tags( $attachment->post_title )); // Finally, use the title
 565  
 566          $attr = wp_parse_args($attr, $default_attr);
 567          $attr = apply_filters( 'wp_get_attachment_image_attributes', $attr, $attachment );
 568          $attr = array_map( 'esc_attr', $attr );
 569          $html = rtrim("<img $hwstring");
 570          foreach ( $attr as $name => $value ) {
 571              $html .= " $name=" . '"' . $value . '"';
 572          }
 573          $html .= ' />';
 574      }
 575  
 576      return $html;
 577  }
 578  
 579  /**
 580   * Adds a 'wp-post-image' class to post thumbnails
 581   * Uses the begin_fetch_post_thumbnail_html and end_fetch_post_thumbnail_html action hooks to
 582   * dynamically add/remove itself so as to only filter post thumbnails
 583   *
 584   * @since 2.9.0
 585   * @param array $attr Attributes including src, class, alt, title
 586   * @return array
 587   */
 588  function _wp_post_thumbnail_class_filter( $attr ) {
 589      $attr['class'] .= ' wp-post-image';
 590      return $attr;
 591  }
 592  
 593  /**
 594   * Adds _wp_post_thumbnail_class_filter to the wp_get_attachment_image_attributes filter
 595   *
 596   * @since 2.9.0
 597   */
 598  function _wp_post_thumbnail_class_filter_add( $attr ) {
 599      add_filter( 'wp_get_attachment_image_attributes', '_wp_post_thumbnail_class_filter' );
 600  }
 601  
 602  /**
 603   * Removes _wp_post_thumbnail_class_filter from the wp_get_attachment_image_attributes filter
 604   *
 605   * @since 2.9.0
 606   */
 607  function _wp_post_thumbnail_class_filter_remove( $attr ) {
 608      remove_filter( 'wp_get_attachment_image_attributes', '_wp_post_thumbnail_class_filter' );
 609  }
 610  
 611  add_shortcode('wp_caption', 'img_caption_shortcode');
 612  add_shortcode('caption', 'img_caption_shortcode');
 613  
 614  /**
 615   * The Caption shortcode.
 616   *
 617   * Allows a plugin to replace the content that would otherwise be returned. The
 618   * filter is 'img_caption_shortcode' and passes an empty string, the attr
 619   * parameter and the content parameter values.
 620   *
 621   * The supported attributes for the shortcode are 'id', 'align', 'width', and
 622   * 'caption'.
 623   *
 624   * @since 2.6.0
 625   *
 626   * @param array $attr Attributes attributed to the shortcode.
 627   * @param string $content Optional. Shortcode content.
 628   * @return string
 629   */
 630  function img_caption_shortcode($attr, $content = null) {
 631      // New-style shortcode with the caption inside the shortcode with the link and image tags.
 632      if ( ! isset( $attr['caption'] ) ) {
 633          if ( preg_match( '#((?:<a [^>]+>\s*)?<img [^>]+>(?:\s*</a>)?)(.*)#is', $content, $matches ) ) {
 634              $content = $matches[1];
 635              $attr['caption'] = trim( $matches[2] );
 636          }
 637      }
 638  
 639      // Allow plugins/themes to override the default caption template.
 640      $output = apply_filters('img_caption_shortcode', '', $attr, $content);
 641      if ( $output != '' )
 642          return $output;
 643  
 644      $atts = shortcode_atts( array(
 645          'id'      => '',
 646          'align'      => 'alignnone',
 647          'width'      => '',
 648          'caption' => ''
 649      ), $attr, 'caption' );
 650  
 651      $atts['width'] = (int) $atts['width'];
 652      if ( $atts['width'] < 1 || empty( $atts['caption'] ) )
 653          return $content;
 654  
 655      if ( ! empty( $atts['id'] ) )
 656          $atts['id'] = 'id="' . esc_attr( $atts['id'] ) . '" ';
 657  
 658      $caption_width = 10 + $atts['width'];
 659  
 660      /**
 661       * Filter the width of an image's caption.
 662       *
 663       * By default, the caption is 10 pixels greater than the width of the image,
 664       * to prevent post content from running up against a floated image.
 665       *
 666       * @since 3.7.0
 667       *
 668       * @param int $caption_width Width in pixels. To remove this inline style, return zero.
 669       * @param array $atts {
 670       *     The attributes of the caption shortcode.
 671       *
 672       *     @type string 'id'      The ID of the div element for the caption.
 673       *     @type string 'align'   The class name that aligns the caption. Default 'alignnone'.
 674       *     @type int    'width'   The width of the image being captioned.
 675       *     @type string 'caption' The image's caption.
 676       * }
 677       * @param string $content The image element, possibly wrapped in a hyperlink.
 678       */
 679      $caption_width = apply_filters( 'img_caption_shortcode_width', $caption_width, $atts, $content );
 680  
 681      $style = '';
 682      if ( $caption_width )
 683          $style = 'style="width: ' . (int) $caption_width . 'px" ';
 684  
 685      return '<div ' . $atts['id'] . $style . 'class="wp-caption ' . esc_attr( $atts['align'] ) . '">'
 686      . do_shortcode( $content ) . '<p class="wp-caption-text">' . $atts['caption'] . '</p></div>';
 687  }
 688  
 689  add_shortcode('gallery', 'gallery_shortcode');
 690  
 691  /**
 692   * The Gallery shortcode.
 693   *
 694   * This implements the functionality of the Gallery Shortcode for displaying
 695   * WordPress images on a post.
 696   *
 697   * @since 2.5.0
 698   *
 699   * @param array $attr Attributes of the shortcode.
 700   * @return string HTML content to display gallery.
 701   */
 702  function gallery_shortcode($attr) {
 703      $post = get_post();
 704  
 705      static $instance = 0;
 706      $instance++;
 707  
 708      if ( ! empty( $attr['ids'] ) ) {
 709          // 'ids' is explicitly ordered, unless you specify otherwise.
 710          if ( empty( $attr['orderby'] ) )
 711              $attr['orderby'] = 'post__in';
 712          $attr['include'] = $attr['ids'];
 713      }
 714  
 715      // Allow plugins/themes to override the default gallery template.
 716      $output = apply_filters('post_gallery', '', $attr);
 717      if ( $output != '' )
 718          return $output;
 719  
 720      // We're trusting author input, so let's at least make sure it looks like a valid orderby statement
 721      if ( isset( $attr['orderby'] ) ) {
 722          $attr['orderby'] = sanitize_sql_orderby( $attr['orderby'] );
 723          if ( !$attr['orderby'] )
 724              unset( $attr['orderby'] );
 725      }
 726  
 727      extract(shortcode_atts(array(
 728          'order'      => 'ASC',
 729          'orderby'    => 'menu_order ID',
 730          'id'         => $post ? $post->ID : 0,
 731          'itemtag'    => 'dl',
 732          'icontag'    => 'dt',
 733          'captiontag' => 'dd',
 734          'columns'    => 3,
 735          'size'       => 'thumbnail',
 736          'include'    => '',
 737          'exclude'    => '',
 738          'link'       => ''
 739      ), $attr, 'gallery'));
 740  
 741      $id = intval($id);
 742      if ( 'RAND' == $order )
 743          $orderby = 'none';
 744  
 745      if ( !empty($include) ) {
 746          $_attachments = get_posts( array('include' => $include, 'post_status' => 'inherit', 'post_type' => 'attachment', 'post_mime_type' => 'image', 'order' => $order, 'orderby' => $orderby) );
 747  
 748          $attachments = array();
 749          foreach ( $_attachments as $key => $val ) {
 750              $attachments[$val->ID] = $_attachments[$key];
 751          }
 752      } elseif ( !empty($exclude) ) {
 753          $attachments = get_children( array('post_parent' => $id, 'exclude' => $exclude, 'post_status' => 'inherit', 'post_type' => 'attachment', 'post_mime_type' => 'image', 'order' => $order, 'orderby' => $orderby) );
 754      } else {
 755          $attachments = get_children( array('post_parent' => $id, 'post_status' => 'inherit', 'post_type' => 'attachment', 'post_mime_type' => 'image', 'order' => $order, 'orderby' => $orderby) );
 756      }
 757  
 758      if ( empty($attachments) )
 759          return '';
 760  
 761      if ( is_feed() ) {
 762          $output = "\n";
 763          foreach ( $attachments as $att_id => $attachment )
 764              $output .= wp_get_attachment_link($att_id, $size, true) . "\n";
 765          return $output;
 766      }
 767  
 768      $itemtag = tag_escape($itemtag);
 769      $captiontag = tag_escape($captiontag);
 770      $icontag = tag_escape($icontag);
 771      $valid_tags = wp_kses_allowed_html( 'post' );
 772      if ( ! isset( $valid_tags[ $itemtag ] ) )
 773          $itemtag = 'dl';
 774      if ( ! isset( $valid_tags[ $captiontag ] ) )
 775          $captiontag = 'dd';
 776      if ( ! isset( $valid_tags[ $icontag ] ) )
 777          $icontag = 'dt';
 778  
 779      $columns = intval($columns);
 780      $itemwidth = $columns > 0 ? floor(100/$columns) : 100;
 781      $float = is_rtl() ? 'right' : 'left';
 782  
 783      $selector = "gallery-{$instance}";
 784  
 785      $gallery_style = $gallery_div = '';
 786      if ( apply_filters( 'use_default_gallery_style', true ) )
 787          $gallery_style = "
 788          <style type='text/css'>
 789              #{$selector} {
 790                  margin: auto;
 791              }
 792              #{$selector} .gallery-item {
 793                  float: {$float};
 794                  margin-top: 10px;
 795                  text-align: center;
 796                  width: {$itemwidth}%;
 797              }
 798              #{$selector} img {
 799                  border: 2px solid #cfcfcf;
 800              }
 801              #{$selector} .gallery-caption {
 802                  margin-left: 0;
 803              }
 804              /* see gallery_shortcode() in wp-includes/media.php */
 805          </style>";
 806      $size_class = sanitize_html_class( $size );
 807      $gallery_div = "<div id='$selector' class='gallery galleryid-{$id} gallery-columns-{$columns} gallery-size-{$size_class}'>";
 808      $output = apply_filters( 'gallery_style', $gallery_style . "\n\t\t" . $gallery_div );
 809  
 810      $i = 0;
 811      foreach ( $attachments as $id => $attachment ) {
 812          if ( ! empty( $link ) && 'file' === $link )
 813              $image_output = wp_get_attachment_link( $id, $size, false, false );
 814          elseif ( ! empty( $link ) && 'none' === $link )
 815              $image_output = wp_get_attachment_image( $id, $size, false );
 816          else
 817              $image_output = wp_get_attachment_link( $id, $size, true, false );
 818  
 819          $image_meta  = wp_get_attachment_metadata( $id );
 820  
 821          $orientation = '';
 822          if ( isset( $image_meta['height'], $image_meta['width'] ) )
 823              $orientation = ( $image_meta['height'] > $image_meta['width'] ) ? 'portrait' : 'landscape';
 824  
 825          $output .= "<{$itemtag} class='gallery-item'>";
 826          $output .= "
 827              <{$icontag} class='gallery-icon {$orientation}'>
 828                  $image_output
 829              </{$icontag}>";
 830          if ( $captiontag && trim($attachment->post_excerpt) ) {
 831              $output .= "
 832                  <{$captiontag} class='wp-caption-text gallery-caption'>
 833                  " . wptexturize($attachment->post_excerpt) . "
 834                  </{$captiontag}>";
 835          }
 836          $output .= "</{$itemtag}>";
 837          if ( $columns > 0 && ++$i % $columns == 0 )
 838              $output .= '<br style="clear: both" />';
 839      }
 840  
 841      $output .= "
 842              <br style='clear: both;' />
 843          </div>\n";
 844  
 845      return $output;
 846  }
 847  
 848  /**
 849   * Provide a No-JS Flash fallback as a last resort for audio / video
 850   *
 851   * @since 3.6.0
 852   *
 853   * @param string $url
 854   * @return string Fallback HTML
 855   */
 856  function wp_mediaelement_fallback( $url ) {
 857      return apply_filters( 'wp_mediaelement_fallback', sprintf( '<a href="%1$s">%1$s</a>', esc_url( $url ) ), $url );
 858  }
 859  
 860  /**
 861   * Return a filtered list of WP-supported audio formats
 862   *
 863   * @since 3.6.0
 864   * @return array
 865   */
 866  function wp_get_audio_extensions() {
 867      return apply_filters( 'wp_audio_extensions', array( 'mp3', 'ogg', 'wma', 'm4a', 'wav' ) );
 868  }
 869  
 870  /**
 871   * The Audio shortcode.
 872   *
 873   * This implements the functionality of the Audio Shortcode for displaying
 874   * WordPress mp3s in a post.
 875   *
 876   * @since 3.6.0
 877   *
 878   * @param array  $attr    Attributes of the shortcode.
 879   * @param string $content Optional. Shortcode content.
 880   * @return string HTML content to display audio.
 881   */
 882  function wp_audio_shortcode( $attr, $content = '' ) {
 883      $post_id = get_post() ? get_the_ID() : 0;
 884  
 885      static $instances = 0;
 886      $instances++;
 887  
 888      /**
 889       * Override the default audio shortcode.
 890       *
 891       * @since 3.7.0
 892       *
 893       * @param null              Empty variable to be replaced with shortcode markup.
 894       * @param array  $attr      Attributes of the shortcode.
 895       * @param string $content   Shortcode content.
 896       * @param int    $instances Unique numeric ID of this audio shortcode instance.
 897       */
 898      $html = apply_filters( 'wp_audio_shortcode_override', '', $attr, $content, $instances );
 899      if ( '' !== $html )
 900          return $html;
 901  
 902      $audio = null;
 903  
 904      $default_types = wp_get_audio_extensions();
 905      $defaults_atts = array(
 906          'src'      => '',
 907          'loop'     => '',
 908          'autoplay' => '',
 909          'preload'  => 'none'
 910      );
 911      foreach ( $default_types as $type )
 912          $defaults_atts[$type] = '';
 913  
 914      $atts = shortcode_atts( $defaults_atts, $attr, 'audio' );
 915      extract( $atts );
 916  
 917      $primary = false;
 918      if ( ! empty( $src ) ) {
 919          $type = wp_check_filetype( $src, wp_get_mime_types() );
 920          if ( ! in_array( strtolower( $type['ext'] ), $default_types ) )
 921              return sprintf( '<a class="wp-embedded-audio" href="%s">%s</a>', esc_url( $src ), esc_html( $src ) );
 922          $primary = true;
 923          array_unshift( $default_types, 'src' );
 924      } else {
 925          foreach ( $default_types as $ext ) {
 926              if ( ! empty( $$ext ) ) {
 927                  $type = wp_check_filetype( $$ext, wp_get_mime_types() );
 928                  if ( strtolower( $type['ext'] ) === $ext )
 929                      $primary = true;
 930              }
 931          }
 932      }
 933  
 934      if ( ! $primary ) {
 935          $audios = get_attached_media( 'audio', $post_id );
 936          if ( empty( $audios ) )
 937              return;
 938  
 939          $audio = reset( $audios );
 940          $src = wp_get_attachment_url( $audio->ID );
 941          if ( empty( $src ) )
 942              return;
 943  
 944          array_unshift( $default_types, 'src' );
 945      }
 946  
 947      $library = apply_filters( 'wp_audio_shortcode_library', 'mediaelement' );
 948      if ( 'mediaelement' === $library && did_action( 'init' ) ) {
 949          wp_enqueue_style( 'wp-mediaelement' );
 950          wp_enqueue_script( 'wp-mediaelement' );
 951      }
 952  
 953      $atts = array(
 954          'class'    => apply_filters( 'wp_audio_shortcode_class', 'wp-audio-shortcode' ),
 955          'id'       => sprintf( 'audio-%d-%d', $post_id, $instances ),
 956          'loop'     => $loop,
 957          'autoplay' => $autoplay,
 958          'preload'  => $preload,
 959          'style'    => 'width: 100%',
 960      );
 961  
 962      // These ones should just be omitted altogether if they are blank
 963      foreach ( array( 'loop', 'autoplay', 'preload' ) as $a ) {
 964          if ( empty( $atts[$a] ) )
 965              unset( $atts[$a] );
 966      }
 967  
 968      $attr_strings = array();
 969      foreach ( $atts as $k => $v ) {
 970          $attr_strings[] = $k . '="' . esc_attr( $v ) . '"';
 971      }
 972  
 973      $html = '';
 974      if ( 'mediaelement' === $library && 1 === $instances )
 975          $html .= "<!--[if lt IE 9]><script>document.createElement('audio');</script><![endif]-->\n";
 976      $html .= sprintf( '<audio %s controls="controls">', join( ' ', $attr_strings ) );
 977  
 978      $fileurl = '';
 979      $source = '<source type="%s" src="%s" />';
 980      foreach ( $default_types as $fallback ) {
 981          if ( ! empty( $$fallback ) ) {
 982              if ( empty( $fileurl ) )
 983                  $fileurl = $$fallback;
 984              $type = wp_check_filetype( $$fallback, wp_get_mime_types() );
 985              $html .= sprintf( $source, $type['type'], esc_url( $$fallback ) );
 986          }
 987      }
 988  
 989      if ( 'mediaelement' === $library )
 990          $html .= wp_mediaelement_fallback( $fileurl );
 991      $html .= '</audio>';
 992  
 993      return apply_filters( 'wp_audio_shortcode', $html, $atts, $audio, $post_id, $library );
 994  }
 995  add_shortcode( 'audio', 'wp_audio_shortcode' );
 996  
 997  /**
 998   * Return a filtered list of WP-supported video formats
 999   *
1000   * @since 3.6.0
1001   * @return array
1002   */
1003  function wp_get_video_extensions() {
1004      return apply_filters( 'wp_video_extensions', array( 'mp4', 'm4v', 'webm', 'ogv', 'wmv', 'flv' ) );
1005  }
1006  
1007  /**
1008   * The Video shortcode.
1009   *
1010   * This implements the functionality of the Video Shortcode for displaying
1011   * WordPress mp4s in a post.
1012   *
1013   * @since 3.6.0
1014   *
1015   * @param array  $attr    Attributes of the shortcode.
1016   * @param string $content Optional. Shortcode content.
1017   * @return string HTML content to display video.
1018   */
1019  function wp_video_shortcode( $attr, $content = '' ) {
1020      global $content_width;
1021      $post_id = get_post() ? get_the_ID() : 0;
1022  
1023      static $instances = 0;
1024      $instances++;
1025  
1026      /**
1027       * Override the default video shortcode.
1028       *
1029       * @since 3.7.0
1030       *
1031       * @param null              Empty variable to be replaced with shortcode markup.
1032       * @param array  $attr      Attributes of the shortcode.
1033       * @param string $content   Shortcode content.
1034       * @param int    $instances Unique numeric ID of this video shortcode instance.
1035       */
1036      $html = apply_filters( 'wp_video_shortcode_override', '', $attr, $content, $instances );
1037      if ( '' !== $html )
1038          return $html;
1039  
1040      $video = null;
1041  
1042      $default_types = wp_get_video_extensions();
1043      $defaults_atts = array(
1044          'src'      => '',
1045          'poster'   => '',
1046          'loop'     => '',
1047          'autoplay' => '',
1048          'preload'  => 'metadata',
1049          'height'   => 360,
1050          'width'    => empty( $content_width ) ? 640 : $content_width,
1051      );
1052  
1053      foreach ( $default_types as $type )
1054          $defaults_atts[$type] = '';
1055  
1056      $atts = shortcode_atts( $defaults_atts, $attr, 'video' );
1057      extract( $atts );
1058  
1059      $w = $width;
1060      $h = $height;
1061      if ( is_admin() && $width > 600 )
1062          $w = 600;
1063      elseif ( ! is_admin() && $w > $defaults_atts['width'] )
1064          $w = $defaults_atts['width'];
1065  
1066      if ( $w < $width )
1067          $height = round( ( $h * $w ) / $width );
1068  
1069      $width = $w;
1070  
1071      $primary = false;
1072      if ( ! empty( $src ) ) {
1073          $type = wp_check_filetype( $src, wp_get_mime_types() );
1074          if ( ! in_array( strtolower( $type['ext'] ), $default_types ) )
1075              return sprintf( '<a class="wp-embedded-video" href="%s">%s</a>', esc_url( $src ), esc_html( $src ) );
1076          $primary = true;
1077          array_unshift( $default_types, 'src' );
1078      } else {
1079          foreach ( $default_types as $ext ) {
1080              if ( ! empty( $$ext ) ) {
1081                  $type = wp_check_filetype( $$ext, wp_get_mime_types() );
1082                  if ( strtolower( $type['ext'] ) === $ext )
1083                      $primary = true;
1084              }
1085          }
1086      }
1087  
1088      if ( ! $primary ) {
1089          $videos = get_attached_media( 'video', $post_id );
1090          if ( empty( $videos ) )
1091              return;
1092  
1093          $video = reset( $videos );
1094          $src = wp_get_attachment_url( $video->ID );
1095          if ( empty( $src ) )
1096              return;
1097  
1098          array_unshift( $default_types, 'src' );
1099      }
1100  
1101      $library = apply_filters( 'wp_video_shortcode_library', 'mediaelement' );
1102      if ( 'mediaelement' === $library && did_action( 'init' ) ) {
1103          wp_enqueue_style( 'wp-mediaelement' );
1104          wp_enqueue_script( 'wp-mediaelement' );
1105      }
1106  
1107      $atts = array(
1108          'class'    => apply_filters( 'wp_video_shortcode_class', 'wp-video-shortcode' ),
1109          'id'       => sprintf( 'video-%d-%d', $post_id, $instances ),
1110          'width'    => absint( $width ),
1111          'height'   => absint( $height ),
1112          'poster'   => esc_url( $poster ),
1113          'loop'     => $loop,
1114          'autoplay' => $autoplay,
1115          'preload'  => $preload,
1116      );
1117  
1118      // These ones should just be omitted altogether if they are blank
1119      foreach ( array( 'poster', 'loop', 'autoplay', 'preload' ) as $a ) {
1120          if ( empty( $atts[$a] ) )
1121              unset( $atts[$a] );
1122      }
1123  
1124      $attr_strings = array();
1125      foreach ( $atts as $k => $v ) {
1126          $attr_strings[] = $k . '="' . esc_attr( $v ) . '"';
1127      }
1128  
1129      $html = '';
1130      if ( 'mediaelement' === $library && 1 === $instances )
1131          $html .= "<!--[if lt IE 9]><script>document.createElement('video');</script><![endif]-->\n";
1132      $html .= sprintf( '<video %s controls="controls">', join( ' ', $attr_strings ) );
1133  
1134      $fileurl = '';
1135      $source = '<source type="%s" src="%s" />';
1136      foreach ( $default_types as $fallback ) {
1137          if ( ! empty( $$fallback ) ) {
1138              if ( empty( $fileurl ) )
1139                  $fileurl = $$fallback;
1140              $type = wp_check_filetype( $$fallback, wp_get_mime_types() );
1141              // m4v sometimes shows up as video/mpeg which collides with mp4
1142              if ( 'm4v' === $type['ext'] )
1143                  $type['type'] = 'video/m4v';
1144              $html .= sprintf( $source, $type['type'], esc_url( $$fallback ) );
1145          }
1146      }
1147      if ( 'mediaelement' === $library )
1148          $html .= wp_mediaelement_fallback( $fileurl );
1149      $html .= '</video>';
1150  
1151      $html = sprintf( '<div style="width: %dpx; max-width: 100%%;" class="wp-video">%s</div>', $width, $html );
1152      return apply_filters( 'wp_video_shortcode', $html, $atts, $video, $post_id, $library );
1153  }
1154  add_shortcode( 'video', 'wp_video_shortcode' );
1155  
1156  /**
1157   * Display previous image link that has the same post parent.
1158   *
1159   * @since 2.5.0
1160   * @param string $size Optional, default is 'thumbnail'. Size of image, either array or string. 0 or 'none' will default to post_title or $text;
1161   * @param string $text Optional, default is false. If included, link will reflect $text variable.
1162   * @return string HTML content.
1163   */
1164  function previous_image_link($size = 'thumbnail', $text = false) {
1165      adjacent_image_link(true, $size, $text);
1166  }
1167  
1168  /**
1169   * Display next image link that has the same post parent.
1170   *
1171   * @since 2.5.0
1172   * @param string $size Optional, default is 'thumbnail'. Size of image, either array or string. 0 or 'none' will default to post_title or $text;
1173   * @param string $text Optional, default is false. If included, link will reflect $text variable.
1174   * @return string HTML content.
1175   */
1176  function next_image_link($size = 'thumbnail', $text = false) {
1177      adjacent_image_link(false, $size, $text);
1178  }
1179  
1180  /**
1181   * Display next or previous image link that has the same post parent.
1182   *
1183   * Retrieves the current attachment object from the $post global.
1184   *
1185   * @since 2.5.0
1186   *
1187   * @param bool $prev Optional. Default is true to display previous link, false for next.
1188   */
1189  function adjacent_image_link($prev = true, $size = 'thumbnail', $text = false) {
1190      $post = get_post();
1191      $attachments = array_values( get_children( array( 'post_parent' => $post->post_parent, 'post_status' => 'inherit', 'post_type' => 'attachment', 'post_mime_type' => 'image', 'order' => 'ASC', 'orderby' => 'menu_order ID' ) ) );
1192  
1193      foreach ( $attachments as $k => $attachment )
1194          if ( $attachment->ID == $post->ID )
1195              break;
1196  
1197      $k = $prev ? $k - 1 : $k + 1;
1198  
1199      $output = $attachment_id = null;
1200      if ( isset( $attachments[ $k ] ) ) {
1201          $attachment_id = $attachments[ $k ]->ID;
1202          $output = wp_get_attachment_link( $attachment_id, $size, true, false, $text );
1203      }
1204  
1205      $adjacent = $prev ? 'previous' : 'next';
1206      echo apply_filters( "{$adjacent}_image_link", $output, $attachment_id, $size, $text );
1207  }
1208  
1209  /**
1210   * Retrieve taxonomies attached to the attachment.
1211   *
1212   * @since 2.5.0
1213   *
1214   * @param int|array|object $attachment Attachment ID, Attachment data array, or Attachment data object.
1215   * @return array Empty array on failure. List of taxonomies on success.
1216   */
1217  function get_attachment_taxonomies($attachment) {
1218      if ( is_int( $attachment ) )
1219          $attachment = get_post($attachment);
1220      else if ( is_array($attachment) )
1221          $attachment = (object) $attachment;
1222  
1223      if ( ! is_object($attachment) )
1224          return array();
1225  
1226      $filename = basename($attachment->guid);
1227  
1228      $objects = array('attachment');
1229  
1230      if ( false !== strpos($filename, '.') )
1231          $objects[] = 'attachment:' . substr($filename, strrpos($filename, '.') + 1);
1232      if ( !empty($attachment->post_mime_type) ) {
1233          $objects[] = 'attachment:' . $attachment->post_mime_type;
1234          if ( false !== strpos($attachment->post_mime_type, '/') )
1235              foreach ( explode('/', $attachment->post_mime_type) as $token )
1236                  if ( !empty($token) )
1237                      $objects[] = "attachment:$token";
1238      }
1239  
1240      $taxonomies = array();
1241      foreach ( $objects as $object )
1242          if ( $taxes = get_object_taxonomies($object) )
1243              $taxonomies = array_merge($taxonomies, $taxes);
1244  
1245      return array_unique($taxonomies);
1246  }
1247  
1248  /**
1249   * Return all of the taxonomy names that are registered for attachments.
1250   *
1251   * Handles mime-type-specific taxonomies such as attachment:image and attachment:video.
1252   *
1253   * @since 3.5.0
1254   * @see get_attachment_taxonomies()
1255   * @uses get_taxonomies()
1256   *
1257   * @param string $output The type of output to return, either taxonomy 'names' or 'objects'. 'names' is the default.
1258   * @return array The names of all taxonomy of $object_type.
1259   */
1260  function get_taxonomies_for_attachments( $output = 'names' ) {
1261      $taxonomies = array();
1262      foreach ( get_taxonomies( array(), 'objects' ) as $taxonomy ) {
1263          foreach ( $taxonomy->object_type as $object_type ) {
1264              if ( 'attachment' == $object_type || 0 === strpos( $object_type, 'attachment:' ) ) {
1265                  if ( 'names' == $output )
1266                      $taxonomies[] = $taxonomy->name;
1267                  else
1268                      $taxonomies[ $taxonomy->name ] = $taxonomy;
1269                  break;
1270              }
1271          }
1272      }
1273  
1274      return $taxonomies;
1275  }
1276  
1277  /**
1278   * Create new GD image resource with transparency support
1279   * @TODO: Deprecate if possible.
1280   *
1281   * @since 2.9.0
1282   *
1283   * @param int $width Image width
1284   * @param int $height Image height
1285   * @return image resource
1286   */
1287  function wp_imagecreatetruecolor($width, $height) {
1288      $img = imagecreatetruecolor($width, $height);
1289      if ( is_resource($img) && function_exists('imagealphablending') && function_exists('imagesavealpha') ) {
1290          imagealphablending($img, false);
1291          imagesavealpha($img, true);
1292      }
1293      return $img;
1294  }
1295  
1296  /**
1297   * Register an embed handler. This function should probably only be used for sites that do not support oEmbed.
1298   *
1299   * @since 2.9.0
1300   * @see WP_Embed::register_handler()
1301   */
1302  function wp_embed_register_handler( $id, $regex, $callback, $priority = 10 ) {
1303      global $wp_embed;
1304      $wp_embed->register_handler( $id, $regex, $callback, $priority );
1305  }
1306  
1307  /**
1308   * Unregister a previously registered embed handler.
1309   *
1310   * @since 2.9.0
1311   * @see WP_Embed::unregister_handler()
1312   */
1313  function wp_embed_unregister_handler( $id, $priority = 10 ) {
1314      global $wp_embed;
1315      $wp_embed->unregister_handler( $id, $priority );
1316  }
1317  
1318  /**
1319   * Create default array of embed parameters.
1320   *
1321   * The width defaults to the content width as specified by the theme. If the
1322   * theme does not specify a content width, then 500px is used.
1323   *
1324   * The default height is 1.5 times the width, or 1000px, whichever is smaller.
1325   *
1326   * The 'embed_defaults' filter can be used to adjust either of these values.
1327   *
1328   * @since 2.9.0
1329   *
1330   * @return array Default embed parameters.
1331   */
1332  function wp_embed_defaults() {
1333      if ( ! empty( $GLOBALS['content_width'] ) )
1334          $width = (int) $GLOBALS['content_width'];
1335  
1336      if ( empty( $width ) )
1337          $width = 500;
1338  
1339      $height = min( ceil( $width * 1.5 ), 1000 );
1340  
1341      return apply_filters( 'embed_defaults', compact( 'width', 'height' ) );
1342  }
1343  
1344  /**
1345   * Based on a supplied width/height example, return the biggest possible dimensions based on the max width/height.
1346   *
1347   * @since 2.9.0
1348   * @uses wp_constrain_dimensions() This function passes the widths and the heights.
1349   *
1350   * @param int $example_width The width of an example embed.
1351   * @param int $example_height The height of an example embed.
1352   * @param int $max_width The maximum allowed width.
1353   * @param int $max_height The maximum allowed height.
1354   * @return array The maximum possible width and height based on the example ratio.
1355   */
1356  function wp_expand_dimensions( $example_width, $example_height, $max_width, $max_height ) {
1357      $example_width  = (int) $example_width;
1358      $example_height = (int) $example_height;
1359      $max_width      = (int) $max_width;
1360      $max_height     = (int) $max_height;
1361  
1362      return wp_constrain_dimensions( $example_width * 1000000, $example_height * 1000000, $max_width, $max_height );
1363  }
1364  
1365  /**
1366   * Attempts to fetch the embed HTML for a provided URL using oEmbed.
1367   *
1368   * @since 2.9.0
1369   * @see WP_oEmbed
1370   *
1371   * @uses _wp_oembed_get_object()
1372   * @uses WP_oEmbed::get_html()
1373   *
1374   * @param string $url The URL that should be embedded.
1375   * @param array $args Additional arguments and parameters.
1376   * @return bool|string False on failure or the embed HTML on success.
1377   */
1378  function wp_oembed_get( $url, $args = '' ) {
1379      require_once ( ABSPATH . WPINC . '/class-oembed.php' );
1380      $oembed = _wp_oembed_get_object();
1381      return $oembed->get_html( $url, $args );
1382  }
1383  
1384  /**
1385   * Adds a URL format and oEmbed provider URL pair.
1386   *
1387   * @since 2.9.0
1388   * @see WP_oEmbed
1389   *
1390   * @uses _wp_oembed_get_object()
1391   *
1392   * @param string $format The format of URL that this provider can handle. You can use asterisks as wildcards.
1393   * @param string $provider The URL to the oEmbed provider.
1394   * @param boolean $regex Whether the $format parameter is in a regex format.
1395   */
1396  function wp_oembed_add_provider( $format, $provider, $regex = false ) {
1397      require_once ( ABSPATH . WPINC . '/class-oembed.php' );
1398      $oembed = _wp_oembed_get_object();
1399      $oembed->providers[$format] = array( $provider, $regex );
1400  }
1401  
1402  /**
1403   * Removes an oEmbed provider.
1404   *
1405   * @since 3.5.0
1406   * @see WP_oEmbed
1407   *
1408   * @uses _wp_oembed_get_object()
1409   *
1410   * @param string $format The URL format for the oEmbed provider to remove.
1411   */
1412  function wp_oembed_remove_provider( $format ) {
1413      require_once ( ABSPATH . WPINC . '/class-oembed.php' );
1414  
1415      $oembed = _wp_oembed_get_object();
1416  
1417      if ( isset( $oembed->providers[ $format ] ) ) {
1418          unset( $oembed->providers[ $format ] );
1419          return true;
1420      }
1421  
1422      return false;
1423  }
1424  
1425  /**
1426   * Determines if default embed handlers should be loaded.
1427   *
1428   * Checks to make sure that the embeds library hasn't already been loaded. If
1429   * it hasn't, then it will load the embeds library.
1430   *
1431   * @since 2.9.0
1432   */
1433  function wp_maybe_load_embeds() {
1434      if ( ! apply_filters( 'load_default_embeds', true ) )
1435          return;
1436      wp_embed_register_handler( 'googlevideo', '#http://video\.google\.([A-Za-z.]{2,5})/videoplay\?docid=([\d-]+)(.*?)#i', 'wp_embed_handler_googlevideo' );
1437      wp_embed_register_handler( 'audio', '#^https?://.+?\.(' . join( '|', wp_get_audio_extensions() ) . ')$#i', apply_filters( 'wp_audio_embed_handler', 'wp_embed_handler_audio' ), 9999 );
1438      wp_embed_register_handler( 'video', '#^https?://.+?\.(' . join( '|', wp_get_video_extensions() ) . ')$#i', apply_filters( 'wp_video_embed_handler', 'wp_embed_handler_video' ), 9999 );
1439  }
1440  
1441  /**
1442   * The Google Video embed handler callback. Google Video does not support oEmbed.
1443   *
1444   * @see WP_Embed::register_handler()
1445   * @see WP_Embed::shortcode()
1446   *
1447   * @param array $matches The regex matches from the provided regex when calling {@link wp_embed_register_handler()}.
1448   * @param array $attr Embed attributes.
1449   * @param string $url The original URL that was matched by the regex.
1450   * @param array $rawattr The original unmodified attributes.
1451   * @return string The embed HTML.
1452   */
1453  function wp_embed_handler_googlevideo( $matches, $attr, $url, $rawattr ) {
1454      // If the user supplied a fixed width AND height, use it
1455      if ( !empty($rawattr['width']) && !empty($rawattr['height']) ) {
1456          $width  = (int) $rawattr['width'];
1457          $height = (int) $rawattr['height'];
1458      } else {
1459          list( $width, $height ) = wp_expand_dimensions( 425, 344, $attr['width'], $attr['height'] );
1460      }
1461  
1462      return apply_filters( 'embed_googlevideo', '<embed type="application/x-shockwave-flash" src="http://video.google.com/googleplayer.swf?docid=' . esc_attr($matches[2]) . '&amp;hl=en&amp;fs=true" style="width:' . esc_attr($width) . 'px;height:' . esc_attr($height) . 'px" allowFullScreen="true" allowScriptAccess="always" />', $matches, $attr, $url, $rawattr );
1463  }
1464  
1465  /**
1466   * Audio embed handler callback.
1467   *
1468   * @since 3.6.0
1469   *
1470   * @param array $matches The regex matches from the provided regex when calling {@link wp_embed_register_handler()}.
1471   * @param array $attr Embed attributes.
1472   * @param string $url The original URL that was matched by the regex.
1473   * @param array $rawattr The original unmodified attributes.
1474   * @return string The embed HTML.
1475   */
1476  function wp_embed_handler_audio( $matches, $attr, $url, $rawattr ) {
1477      $audio = sprintf( '[audio src="%s" /]', esc_url( $url ) );
1478      return apply_filters( 'wp_embed_handler_audio', $audio, $attr, $url, $rawattr );
1479  }
1480  
1481  /**
1482   * Video embed handler callback.
1483   *
1484   * @since 3.6.0
1485   *
1486   * @param array $matches The regex matches from the provided regex when calling {@link wp_embed_register_handler()}.
1487   * @param array $attr Embed attributes.
1488   * @param string $url The original URL that was matched by the regex.
1489   * @param array $rawattr The original unmodified attributes.
1490   * @return string The embed HTML.
1491   */
1492  function wp_embed_handler_video( $matches, $attr, $url, $rawattr ) {
1493      $dimensions = '';
1494      if ( ! empty( $rawattr['width'] ) && ! empty( $rawattr['height'] ) ) {
1495          $dimensions .= sprintf( 'width="%d" ', (int) $rawattr['width'] );
1496          $dimensions .= sprintf( 'height="%d" ', (int) $rawattr['height'] );
1497      }
1498      $video = sprintf( '[video %s src="%s" /]', $dimensions, esc_url( $url ) );
1499      return apply_filters( 'wp_embed_handler_video', $video, $attr, $url, $rawattr );
1500  }
1501  
1502  /**
1503   * Converts a shorthand byte value to an integer byte value.
1504   *
1505   * @since 2.3.0
1506   *
1507   * @param string $size A shorthand byte value.
1508   * @return int An integer byte value.
1509   */
1510  function wp_convert_hr_to_bytes( $size ) {
1511      $size  = strtolower( $size );
1512      $bytes = (int) $size;
1513      if ( strpos( $size, 'k' ) !== false )
1514          $bytes = intval( $size ) * 1024;
1515      elseif ( strpos( $size, 'm' ) !== false )
1516          $bytes = intval($size) * 1024 * 1024;
1517      elseif ( strpos( $size, 'g' ) !== false )
1518          $bytes = intval( $size ) * 1024 * 1024 * 1024;
1519      return $bytes;
1520  }
1521  
1522  /**
1523   * Determine the maximum upload size allowed in php.ini.
1524   *
1525   * @since 2.5.0
1526   *
1527   * @return int Allowed upload size.
1528   */
1529  function wp_max_upload_size() {
1530      $u_bytes = wp_convert_hr_to_bytes( ini_get( 'upload_max_filesize' ) );
1531      $p_bytes = wp_convert_hr_to_bytes( ini_get( 'post_max_size' ) );
1532      $bytes   = apply_filters( 'upload_size_limit', min( $u_bytes, $p_bytes ), $u_bytes, $p_bytes );
1533      return $bytes;
1534  }
1535  
1536  /**
1537   * Returns a WP_Image_Editor instance and loads file into it.
1538   *
1539   * @since 3.5.0
1540   * @access public
1541   *
1542   * @param string $path Path to file to load
1543   * @param array $args Additional data. Accepts { 'mime_type'=>string, 'methods'=>{string, string, ...} }
1544   * @return WP_Image_Editor|WP_Error
1545   */
1546  function wp_get_image_editor( $path, $args = array() ) {
1547      $args['path'] = $path;
1548  
1549      if ( ! isset( $args['mime_type'] ) ) {
1550          $file_info = wp_check_filetype( $args['path'] );
1551  
1552          // If $file_info['type'] is false, then we let the editor attempt to
1553          // figure out the file type, rather than forcing a failure based on extension.
1554          if ( isset( $file_info ) && $file_info['type'] )
1555              $args['mime_type'] = $file_info['type'];
1556      }
1557  
1558      $implementation = _wp_image_editor_choose( $args );
1559  
1560      if ( $implementation ) {
1561          $editor = new $implementation( $path );
1562          $loaded = $editor->load();
1563  
1564          if ( is_wp_error( $loaded ) )
1565              return $loaded;
1566  
1567          return $editor;
1568      }
1569  
1570      return new WP_Error( 'image_no_editor', __('No editor could be selected.') );
1571  }
1572  
1573  /**
1574   * Tests whether there is an editor that supports a given mime type or methods.
1575   *
1576   * @since 3.5.0
1577   * @access public
1578   *
1579   * @param string|array $args Array of requirements. Accepts { 'mime_type'=>string, 'methods'=>{string, string, ...} }
1580   * @return boolean true if an eligible editor is found; false otherwise
1581   */
1582  function wp_image_editor_supports( $args = array() ) {
1583      return (bool) _wp_image_editor_choose( $args );
1584  }
1585  
1586  /**
1587   * Tests which editors are capable of supporting the request.
1588   *
1589   * @since 3.5.0
1590   * @access private
1591   *
1592   * @param array $args Additional data. Accepts { 'mime_type'=>string, 'methods'=>{string, string, ...} }
1593   * @return string|bool Class name for the first editor that claims to support the request. False if no editor claims to support the request.
1594   */
1595  function _wp_image_editor_choose( $args = array() ) {
1596      require_once  ABSPATH . WPINC . '/class-wp-image-editor.php';
1597      require_once  ABSPATH . WPINC . '/class-wp-image-editor-gd.php';
1598      require_once  ABSPATH . WPINC . '/class-wp-image-editor-imagick.php';
1599  
1600      $implementations = apply_filters( 'wp_image_editors',
1601          array( 'WP_Image_Editor_Imagick', 'WP_Image_Editor_GD' ) );
1602  
1603      foreach ( $implementations as $implementation ) {
1604          if ( ! call_user_func( array( $implementation, 'test' ), $args ) )
1605              continue;
1606  
1607          if ( isset( $args['mime_type'] ) &&
1608              ! call_user_func(
1609                  array( $implementation, 'supports_mime_type' ),
1610                  $args['mime_type'] ) ) {
1611              continue;
1612          }
1613  
1614          if ( isset( $args['methods'] ) &&
1615               array_diff( $args['methods'], get_class_methods( $implementation ) ) ) {
1616              continue;
1617          }
1618  
1619          return $implementation;
1620      }
1621  
1622      return false;
1623  }
1624  
1625  /**
1626   * Prints default plupload arguments.
1627   *
1628   * @since 3.4.0
1629   */
1630  function wp_plupload_default_settings() {
1631      global $wp_scripts;
1632  
1633      $data = $wp_scripts->get_data( 'wp-plupload', 'data' );
1634      if ( $data && false !== strpos( $data, '_wpPluploadSettings' ) )
1635          return;
1636  
1637      $max_upload_size = wp_max_upload_size();
1638  
1639      $defaults = array(
1640          'runtimes'            => 'html5,silverlight,flash,html4',
1641          'file_data_name'      => 'async-upload', // key passed to $_FILE.
1642          'multiple_queues'     => true,
1643          'max_file_size'       => $max_upload_size . 'b',
1644          'url'                 => admin_url( 'async-upload.php', 'relative' ),
1645          'flash_swf_url'       => includes_url( 'js/plupload/plupload.flash.swf' ),
1646          'silverlight_xap_url' => includes_url( 'js/plupload/plupload.silverlight.xap' ),
1647          'filters'             => array( array( 'title' => __( 'Allowed Files' ), 'extensions' => '*') ),
1648          'multipart'           => true,
1649          'urlstream_upload'    => true,
1650      );
1651  
1652      // Multi-file uploading doesn't currently work in iOS Safari,
1653      // single-file allows the built-in camera to be used as source for images
1654      if ( wp_is_mobile() )
1655          $defaults['multi_selection'] = false;
1656  
1657      $defaults = apply_filters( 'plupload_default_settings', $defaults );
1658  
1659      $params = array(
1660          'action' => 'upload-attachment',
1661      );
1662  
1663      $params = apply_filters( 'plupload_default_params', $params );
1664      $params['_wpnonce'] = wp_create_nonce( 'media-form' );
1665      $defaults['multipart_params'] = $params;
1666  
1667      $settings = array(
1668          'defaults' => $defaults,
1669          'browser'  => array(
1670              'mobile'    => wp_is_mobile(),
1671              'supported' => _device_can_upload(),
1672          ),
1673          'limitExceeded' => is_multisite() && ! is_upload_space_available()
1674      );
1675  
1676      $script = 'var _wpPluploadSettings = ' . json_encode( $settings ) . ';';
1677  
1678      if ( $data )
1679          $script = "$data\n$script";
1680  
1681      $wp_scripts->add_data( 'wp-plupload', 'data', $script );
1682  }
1683  add_action( 'customize_controls_enqueue_scripts', 'wp_plupload_default_settings' );
1684  
1685  /**
1686   * Prepares an attachment post object for JS, where it is expected
1687   * to be JSON-encoded and fit into an Attachment model.
1688   *
1689   * @since 3.5.0
1690   *
1691   * @param mixed $attachment Attachment ID or object.
1692   * @return array Array of attachment details.
1693   */
1694  function wp_prepare_attachment_for_js( $attachment ) {
1695      if ( ! $attachment = get_post( $attachment ) )
1696          return;
1697  
1698      if ( 'attachment' != $attachment->post_type )
1699          return;
1700  
1701      $meta = wp_get_attachment_metadata( $attachment->ID );
1702      if ( false !== strpos( $attachment->post_mime_type, '/' ) )
1703          list( $type, $subtype ) = explode( '/', $attachment->post_mime_type );
1704      else
1705          list( $type, $subtype ) = array( $attachment->post_mime_type, '' );
1706  
1707      $attachment_url = wp_get_attachment_url( $attachment->ID );
1708  
1709      $response = array(
1710          'id'          => $attachment->ID,
1711          'title'       => $attachment->post_title,
1712          'filename'    => wp_basename( $attachment->guid ),
1713          'url'         => $attachment_url,
1714          'link'        => get_attachment_link( $attachment->ID ),
1715          'alt'         => get_post_meta( $attachment->ID, '_wp_attachment_image_alt', true ),
1716          'author'      => $attachment->post_author,
1717          'description' => $attachment->post_content,
1718          'caption'     => $attachment->post_excerpt,
1719          'name'        => $attachment->post_name,
1720          'status'      => $attachment->post_status,
1721          'uploadedTo'  => $attachment->post_parent,
1722          'date'        => strtotime( $attachment->post_date_gmt ) * 1000,
1723          'modified'    => strtotime( $attachment->post_modified_gmt ) * 1000,
1724          'menuOrder'   => $attachment->menu_order,
1725          'mime'        => $attachment->post_mime_type,
1726          'type'        => $type,
1727          'subtype'     => $subtype,
1728          'icon'        => wp_mime_type_icon( $attachment->ID ),
1729          'dateFormatted' => mysql2date( get_option('date_format'), $attachment->post_date ),
1730          'nonces'      => array(
1731              'update' => false,
1732              'delete' => false,
1733          ),
1734          'editLink'   => false,
1735      );
1736  
1737      if ( current_user_can( 'edit_post', $attachment->ID ) ) {
1738          $response['nonces']['update'] = wp_create_nonce( 'update-post_' . $attachment->ID );
1739          $response['editLink'] = get_edit_post_link( $attachment->ID, 'raw' );
1740      }
1741  
1742      if ( current_user_can( 'delete_post', $attachment->ID ) )
1743          $response['nonces']['delete'] = wp_create_nonce( 'delete-post_' . $attachment->ID );
1744  
1745      if ( $meta && 'image' === $type ) {
1746          $sizes = array();
1747          /** This filter is documented in wp-admin/includes/media.php */
1748          $possible_sizes = apply_filters( 'image_size_names_choose', array(
1749              'thumbnail' => __('Thumbnail'),
1750              'medium'    => __('Medium'),
1751              'large'     => __('Large'),
1752              'full'      => __('Full Size'),
1753          ) );
1754          unset( $possible_sizes['full'] );
1755  
1756          // Loop through all potential sizes that may be chosen. Try to do this with some efficiency.
1757          // First: run the image_downsize filter. If it returns something, we can use its data.
1758          // If the filter does not return something, then image_downsize() is just an expensive
1759          // way to check the image metadata, which we do second.
1760          foreach ( $possible_sizes as $size => $label ) {
1761              if ( $downsize = apply_filters( 'image_downsize', false, $attachment->ID, $size ) ) {
1762                  if ( ! $downsize[3] )
1763                      continue;
1764                  $sizes[ $size ] = array(
1765                      'height'      => $downsize[2],
1766                      'width'       => $downsize[1],
1767                      'url'         => $downsize[0],
1768                      'orientation' => $downsize[2] > $downsize[1] ? 'portrait' : 'landscape',
1769                  );
1770              } elseif ( isset( $meta['sizes'][ $size ] ) ) {
1771                  if ( ! isset( $base_url ) )
1772                      $base_url = str_replace( wp_basename( $attachment_url ), '', $attachment_url );
1773  
1774                  // Nothing from the filter, so consult image metadata if we have it.
1775                  $size_meta = $meta['sizes'][ $size ];
1776  
1777                  // We have the actual image size, but might need to further constrain it if content_width is narrower.
1778                  // Thumbnail, medium, and full sizes are also checked against the site's height/width options.
1779                  list( $width, $height ) = image_constrain_size_for_editor( $size_meta['width'], $size_meta['height'], $size, 'edit' );
1780  
1781                  $sizes[ $size ] = array(
1782                      'height'      => $height,
1783                      'width'       => $width,
1784                      'url'         => $base_url . $size_meta['file'],
1785                      'orientation' => $height > $width ? 'portrait' : 'landscape',
1786                  );
1787              }
1788          }
1789  
1790          $sizes['full'] = array( 'url' => $attachment_url );
1791  
1792          if ( isset( $meta['height'], $meta['width'] ) ) {
1793              $sizes['full']['height'] = $meta['height'];
1794              $sizes['full']['width'] = $meta['width'];
1795              $sizes['full']['orientation'] = $meta['height'] > $meta['width'] ? 'portrait' : 'landscape';
1796          }
1797  
1798          $response = array_merge( $response, array( 'sizes' => $sizes ), $sizes['full'] );
1799      } elseif ( $meta && 'video' === $type ) {
1800          if ( isset( $meta['width'] ) )
1801              $response['width'] = (int) $meta['width'];
1802          if ( isset( $meta['height'] ) )
1803              $response['height'] = (int) $meta['height'];
1804      }
1805  
1806      if ( $meta && ( 'audio' === $type || 'video' === $type ) ) {
1807          if ( isset( $meta['length_formatted'] ) )
1808              $response['fileLength'] = $meta['length_formatted'];
1809      }
1810  
1811      if ( function_exists('get_compat_media_markup') )
1812          $response['compat'] = get_compat_media_markup( $attachment->ID, array( 'in_modal' => true ) );
1813  
1814      return apply_filters( 'wp_prepare_attachment_for_js', $response, $attachment, $meta );
1815  }
1816  
1817  /**
1818   * Enqueues all scripts, styles, settings, and templates necessary to use
1819   * all media JS APIs.
1820   *
1821   * @since 3.5.0
1822   */
1823  function wp_enqueue_media( $args = array() ) {
1824  
1825      // Enqueue me just once per page, please.
1826      if ( did_action( 'wp_enqueue_media' ) )
1827          return;
1828  
1829      $defaults = array(
1830          'post' => null,
1831      );
1832      $args = wp_parse_args( $args, $defaults );
1833  
1834      // We're going to pass the old thickbox media tabs to `media_upload_tabs`
1835      // to ensure plugins will work. We will then unset those tabs.
1836      $tabs = array(
1837          // handler action suffix => tab label
1838          'type'     => '',
1839          'type_url' => '',
1840          'gallery'  => '',
1841          'library'  => '',
1842      );
1843  
1844      $tabs = apply_filters( 'media_upload_tabs', $tabs );
1845      unset( $tabs['type'], $tabs['type_url'], $tabs['gallery'], $tabs['library'] );
1846  
1847      $props = array(
1848          'link'  => get_option( 'image_default_link_type' ), // db default is 'file'
1849          'align' => get_option( 'image_default_align' ), // empty default
1850          'size'  => get_option( 'image_default_size' ),  // empty default
1851      );
1852  
1853      $settings = array(
1854          'tabs'      => $tabs,
1855          'tabUrl'    => add_query_arg( array( 'chromeless' => true ), admin_url('media-upload.php') ),
1856          'mimeTypes' => wp_list_pluck( get_post_mime_types(), 0 ),
1857          'captions'  => ! apply_filters( 'disable_captions', '' ),
1858          'nonce'     => array(
1859              'sendToEditor' => wp_create_nonce( 'media-send-to-editor' ),
1860          ),
1861          'post'    => array(
1862              'id' => 0,
1863          ),
1864          'defaultProps' => $props,
1865          'embedExts'    => array_merge( wp_get_audio_extensions(), wp_get_video_extensions() ),
1866      );
1867  
1868      $post = null;
1869      if ( isset( $args['post'] ) ) {
1870          $post = get_post( $args['post'] );
1871          $settings['post'] = array(
1872              'id' => $post->ID,
1873              'nonce' => wp_create_nonce( 'update-post_' . $post->ID ),
1874          );
1875  
1876          if ( current_theme_supports( 'post-thumbnails', $post->post_type ) && post_type_supports( $post->post_type, 'thumbnail' ) ) {
1877              $featured_image_id = get_post_meta( $post->ID, '_thumbnail_id', true );
1878              $settings['post']['featuredImageId'] = $featured_image_id ? $featured_image_id : -1;
1879          }
1880      }
1881  
1882      $hier = $post && is_post_type_hierarchical( $post->post_type );
1883  
1884      $strings = array(
1885          // Generic
1886          'url'         => __( 'URL' ),
1887          'addMedia'    => __( 'Add Media' ),
1888          'search'      => __( 'Search' ),
1889          'select'      => __( 'Select' ),
1890          'cancel'      => __( 'Cancel' ),
1891          /* translators: This is a would-be plural string used in the media manager.
1892             If there is not a word you can use in your language to avoid issues with the
1893             lack of plural support here, turn it into "selected: %d" then translate it.
1894           */
1895          'selected'    => __( '%d selected' ),
1896          'dragInfo'    => __( 'Drag and drop to reorder images.' ),
1897  
1898          // Upload
1899          'uploadFilesTitle'  => __( 'Upload Files' ),
1900          'uploadImagesTitle' => __( 'Upload Images' ),
1901  
1902          // Library
1903          'mediaLibraryTitle'  => __( 'Media Library' ),
1904          'insertMediaTitle'   => __( 'Insert Media' ),
1905          'createNewGallery'   => __( 'Create a new gallery' ),
1906          'returnToLibrary'    => __( '&#8592; Return to library' ),
1907          'allMediaItems'      => __( 'All media items' ),
1908          'noItemsFound'       => __( 'No items found.' ),
1909          'insertIntoPost'     => $hier ? __( 'Insert into page' ) : __( 'Insert into post' ),
1910          'uploadedToThisPost' => $hier ? __( 'Uploaded to this page' ) : __( 'Uploaded to this post' ),
1911          'warnDelete' =>      __( "You are about to permanently delete this item.\n  'Cancel' to stop, 'OK' to delete." ),
1912  
1913          // From URL
1914          'insertFromUrlTitle' => __( 'Insert from URL' ),
1915  
1916          // Featured Images
1917          'setFeaturedImageTitle' => __( 'Set Featured Image' ),
1918          'setFeaturedImage'    => __( 'Set featured image' ),
1919  
1920          // Gallery
1921          'createGalleryTitle' => __( 'Create Gallery' ),
1922          'editGalleryTitle'   => __( 'Edit Gallery' ),
1923          'cancelGalleryTitle' => __( '&#8592; Cancel Gallery' ),
1924          'insertGallery'      => __( 'Insert gallery' ),
1925          'updateGallery'      => __( 'Update gallery' ),
1926          'addToGallery'       => __( 'Add to gallery' ),
1927          'addToGalleryTitle'  => __( 'Add to Gallery' ),
1928          'reverseOrder'       => __( 'Reverse order' ),
1929      );
1930  
1931      $settings = apply_filters( 'media_view_settings', $settings, $post );
1932      $strings  = apply_filters( 'media_view_strings',  $strings,  $post );
1933  
1934      $strings['settings'] = $settings;
1935  
1936      wp_localize_script( 'media-views', '_wpMediaViewsL10n', $strings );
1937  
1938      wp_enqueue_script( 'media-editor' );
1939      wp_enqueue_style( 'media-views' );
1940      wp_plupload_default_settings();
1941  
1942      require_once  ABSPATH . WPINC . '/media-template.php';
1943      add_action( 'admin_footer', 'wp_print_media_templates' );
1944      add_action( 'wp_footer', 'wp_print_media_templates' );
1945      add_action( 'customize_controls_print_footer_scripts', 'wp_print_media_templates' );
1946  
1947      do_action( 'wp_enqueue_media' );
1948  }
1949  
1950  /**
1951   * Retrieve media attached to the passed post
1952   *
1953   * @since 3.6.0
1954   *
1955   * @param string $type (Mime) type of media desired
1956   * @param mixed $post Post ID or object
1957   * @return array Found attachments
1958   */
1959  function get_attached_media( $type, $post = 0 ) {
1960      if ( ! $post = get_post( $post ) )
1961          return array();
1962  
1963      $args = array(
1964          'post_parent' => $post->ID,
1965          'post_type' => 'attachment',
1966          'post_mime_type' => $type,
1967          'posts_per_page' => -1,
1968          'orderby' => 'menu_order',
1969          'order' => 'ASC',
1970      );
1971  
1972      $args = apply_filters( 'get_attached_media_args', $args, $type, $post );
1973  
1974      $children = get_children( $args );
1975  
1976      return (array) apply_filters( 'get_attached_media', $children, $type, $post );
1977  }
1978  
1979  /**
1980   * Check the content blob for an <audio>, <video> <object>, <embed>, or <iframe>
1981   *
1982   * @since 3.6.0
1983   *
1984   * @param string $content A string which might contain media data.
1985   * @param array $types array of media types: 'audio', 'video', 'object', 'embed', or 'iframe'
1986   * @return array A list of found HTML media embeds
1987   */
1988  function get_media_embedded_in_content( $content, $types = null ) {
1989      $html = array();
1990      $allowed_media_types = array( 'audio', 'video', 'object', 'embed', 'iframe' );
1991      if ( ! empty( $types ) ) {
1992          if ( ! is_array( $types ) )
1993              $types = array( $types );
1994          $allowed_media_types = array_intersect( $allowed_media_types, $types );
1995      }
1996  
1997      foreach ( $allowed_media_types as $tag ) {
1998          if ( preg_match( '#' . get_tag_regex( $tag ) . '#', $content, $matches ) ) {
1999              $html[] = $matches[0];
2000          }
2001      }
2002  
2003      return $html;
2004  }
2005  
2006  /**
2007   * Retrieve galleries from the passed post's content
2008   *
2009   * @since 3.6.0
2010   *
2011   * @param mixed $post Optional. Post ID or object.
2012   * @param boolean $html Whether to return HTML or data in the array
2013   * @return array A list of arrays, each containing gallery data and srcs parsed
2014   *        from the expanded shortcode
2015   */
2016  function get_post_galleries( $post, $html = true ) {
2017      if ( ! $post = get_post( $post ) )
2018          return array();
2019  
2020      if ( ! has_shortcode( $post->post_content, 'gallery' ) )
2021          return array();
2022  
2023      $galleries = array();
2024      if ( preg_match_all( '/' . get_shortcode_regex() . '/s', $post->post_content, $matches, PREG_SET_ORDER ) ) {
2025          foreach ( $matches as $shortcode ) {
2026              if ( 'gallery' === $shortcode[2] ) {
2027                  $srcs = array();
2028                  $count = 1;
2029  
2030                  $gallery = do_shortcode_tag( $shortcode );
2031                  if ( $html ) {
2032                      $galleries[] = $gallery;
2033                  } else {
2034                      preg_match_all( '#src=([\'"])(.+?)\1#is', $gallery, $src, PREG_SET_ORDER );
2035                      if ( ! empty( $src ) ) {
2036                          foreach ( $src as $s )
2037                              $srcs[] = $s[2];
2038                      }
2039  
2040                      $data = shortcode_parse_atts( $shortcode[3] );
2041                      $data['src'] = array_values( array_unique( $srcs ) );
2042                      $galleries[] = $data;
2043                  }
2044              }
2045          }
2046      }
2047  
2048      return apply_filters( 'get_post_galleries', $galleries, $post );
2049  }
2050  
2051  /**
2052   * Check a specified post's content for gallery and, if present, return the first
2053   *
2054   * @since 3.6.0
2055   *
2056   * @param mixed $post Optional. Post ID or object.
2057   * @param boolean $html Whether to return HTML or data
2058   * @return string|array Gallery data and srcs parsed from the expanded shortcode
2059   */
2060  function get_post_gallery( $post = 0, $html = true ) {
2061      $galleries = get_post_galleries( $post, $html );
2062      $gallery = reset( $galleries );
2063  
2064      return apply_filters( 'get_post_gallery', $gallery, $post, $galleries );
2065  }
2066  
2067  /**
2068   * Retrieve the image srcs from galleries from a post's content, if present
2069   *
2070   * @since 3.6.0
2071   *
2072   * @param mixed $post Optional. Post ID or object.
2073   * @return array A list of lists, each containing image srcs parsed
2074   *        from an expanded shortcode
2075   */
2076  function get_post_galleries_images( $post = 0 ) {
2077      $galleries = get_post_galleries( $post, false );
2078      return wp_list_pluck( $galleries, 'src' );
2079  }
2080  
2081  /**
2082   * Check a post's content for galleries and return the image srcs for the first found gallery
2083   *
2084   * @since 3.6.0
2085   *
2086   * @param mixed $post Optional. Post ID or object.
2087   * @return array A list of a gallery's image srcs in order
2088   */
2089  function get_post_gallery_images( $post = 0 ) {
2090      $gallery = get_post_gallery( $post, false );
2091      return empty( $gallery['src'] ) ? array() : $gallery['src'];
2092  }


Generated: Tue Mar 25 01:41:18 2014 WordPress honlapkészítés: online1.hu