Make WordPress Core

Changeset 21999


Ignore:
Timestamp:
09/25/2012 08:39:26 AM (12 years ago)
Author:
nacin
Message:

Move WP_Embed into its own file. props ocean90. fixes #20533.

Location:
trunk
Files:
2 edited
1 copied

Legend:

Unmodified
Added
Removed
  • trunk/wp-includes/class-wp-embed.php

    r21998 r21999  
    11<?php
    2 /**
    3  * WordPress API for media display.
    4  *
    5  * @package WordPress
    6  */
    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 'editor_max_image_size', that will be called
    21  * 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  * @uses wp_constrain_dimensions() This function passes the widths and the heights.
    28  *
    29  * @param int $width Width of the image
    30  * @param int $height Height of the image
    31  * @param string|array $size Size of what the result image should be.
    32  * @return array Width and height of what the result image should resize to.
    33  */
    34 function image_constrain_size_for_editor($width, $height, $size = 'medium') {
    35     global $content_width, $_wp_additional_image_sizes;
    36 
    37     if ( is_array($size) ) {
    38         $max_width = $size[0];
    39         $max_height = $size[1];
    40     }
    41     elseif ( $size == 'thumb' || $size == 'thumbnail' ) {
    42         $max_width = intval(get_option('thumbnail_size_w'));
    43         $max_height = intval(get_option('thumbnail_size_h'));
    44         // last chance thumbnail size defaults
    45         if ( !$max_width && !$max_height ) {
    46             $max_width = 128;
    47             $max_height = 96;
    48         }
    49     }
    50     elseif ( $size == 'medium' ) {
    51         $max_width = intval(get_option('medium_size_w'));
    52         $max_height = intval(get_option('medium_size_h'));
    53         // if no width is set, default to the theme content width if available
    54     }
    55     elseif ( $size == 'large' ) {
    56         // We're inserting a large size image into the editor. If it's a really
    57         // big image we'll scale it down to fit reasonably within the editor
    58         // itself, and within the theme's content width if it's known. The user
    59         // can resize it in the editor if they wish.
    60         $max_width = intval(get_option('large_size_w'));
    61         $max_height = intval(get_option('large_size_h'));
    62         if ( intval($content_width) > 0 )
    63             $max_width = min( intval($content_width), $max_width );
    64     } elseif ( isset( $_wp_additional_image_sizes ) && count( $_wp_additional_image_sizes ) && in_array( $size, array_keys( $_wp_additional_image_sizes ) ) ) {
    65         $max_width = intval( $_wp_additional_image_sizes[$size]['width'] );
    66         $max_height = intval( $_wp_additional_image_sizes[$size]['height'] );
    67         if ( intval($content_width) > 0 && is_admin() ) // Only in admin. Assume that theme authors know what they're doing.
    68             $max_width = min( intval($content_width), $max_width );
    69     }
    70     // $size == 'full' has no constraint
    71     else {
    72         $max_width = $width;
    73         $max_height = $height;
    74     }
    75 
    76     list( $max_width, $max_height ) = apply_filters( 'editor_max_image_size', array( $max_width, $max_height ), $size );
    77 
    78     return wp_constrain_dimensions( $width, $height, $max_width, $max_height );
    79 }
    80 
    81 /**
    82  * Retrieve width and height attributes using given width and height values.
    83  *
    84  * Both attributes are required in the sense that both parameters must have a
    85  * value, but are optional in that if you set them to false or null, then they
    86  * will not be added to the returned string.
    87  *
    88  * You can set the value using a string, but it will only take numeric values.
    89  * If you wish to put 'px' after the numbers, then it will be stripped out of
    90  * the return.
    91  *
    92  * @since 2.5.0
    93  *
    94  * @param int|string $width Optional. Width attribute value.
    95  * @param int|string $height Optional. Height attribute value.
    96  * @return string HTML attributes for width and, or height.
    97  */
    98 function image_hwstring($width, $height) {
    99     $out = '';
    100     if ($width)
    101         $out .= 'width="'.intval($width).'" ';
    102     if ($height)
    103         $out .= 'height="'.intval($height).'" ';
    104     return $out;
    105 }
    106 
    107 /**
    108  * Scale an image to fit a particular size (such as 'thumb' or 'medium').
    109  *
    110  * Array with image url, width, height, and whether is intermediate size, in
    111  * that order is returned on success is returned. $is_intermediate is true if
    112  * $url is a resized image, false if it is the original.
    113  *
    114  * The URL might be the original image, or it might be a resized version. This
    115  * function won't create a new resized copy, it will just return an already
    116  * resized one if it exists.
    117  *
    118  * A plugin may use the 'image_downsize' filter to hook into and offer image
    119  * resizing services for images. The hook must return an array with the same
    120  * elements that are returned in the function. The first element being the URL
    121  * to the new image that was resized.
    122  *
    123  * @since 2.5.0
    124  * @uses apply_filters() Calls 'image_downsize' on $id and $size to provide
    125  *      resize services.
    126  *
    127  * @param int $id Attachment ID for image.
    128  * @param array|string $size Optional, default is 'medium'. Size of image, either array or string.
    129  * @return bool|array False on failure, array on success.
    130  */
    131 function image_downsize($id, $size = 'medium') {
    132 
    133     if ( !wp_attachment_is_image($id) )
    134         return false;
    135 
    136     $img_url = wp_get_attachment_url($id);
    137     $meta = wp_get_attachment_metadata($id);
    138     $width = $height = 0;
    139     $is_intermediate = false;
    140     $img_url_basename = wp_basename($img_url);
    141 
    142     // plugins can use this to provide resize services
    143     if ( $out = apply_filters('image_downsize', false, $id, $size) )
    144         return $out;
    145 
    146     // try for a new style intermediate size
    147     if ( $intermediate = image_get_intermediate_size($id, $size) ) {
    148         $img_url = str_replace($img_url_basename, $intermediate['file'], $img_url);
    149         $width = $intermediate['width'];
    150         $height = $intermediate['height'];
    151         $is_intermediate = true;
    152     }
    153     elseif ( $size == 'thumbnail' ) {
    154         // fall back to the old thumbnail
    155         if ( ($thumb_file = wp_get_attachment_thumb_file($id)) && $info = getimagesize($thumb_file) ) {
    156             $img_url = str_replace($img_url_basename, wp_basename($thumb_file), $img_url);
    157             $width = $info[0];
    158             $height = $info[1];
    159             $is_intermediate = true;
    160         }
    161     }
    162     if ( !$width && !$height && isset($meta['width'], $meta['height']) ) {
    163         // any other type: use the real image
    164         $width = $meta['width'];
    165         $height = $meta['height'];
    166     }
    167 
    168     if ( $img_url) {
    169         // we have the actual image size, but might need to further constrain it if content_width is narrower
    170         list( $width, $height ) = image_constrain_size_for_editor( $width, $height, $size );
    171 
    172         return array( $img_url, $width, $height, $is_intermediate );
    173     }
    174     return false;
    175 
    176 }
    177 
    178 /**
    179  * Registers a new image size
    180  *
    181  * @since 2.9.0
    182  */
    183 function add_image_size( $name, $width = 0, $height = 0, $crop = false ) {
    184     global $_wp_additional_image_sizes;
    185     $_wp_additional_image_sizes[$name] = array( 'width' => absint( $width ), 'height' => absint( $height ), 'crop' => (bool) $crop );
    186 }
    187 
    188 /**
    189  * Registers an image size for the post thumbnail
    190  *
    191  * @since 2.9.0
    192  */
    193 function set_post_thumbnail_size( $width = 0, $height = 0, $crop = false ) {
    194     add_image_size( 'post-thumbnail', $width, $height, $crop );
    195 }
    196 
    197 /**
    198  * An <img src /> tag for an image attachment, scaling it down if requested.
    199  *
    200  * The filter 'get_image_tag_class' allows for changing the class name for the
    201  * image without having to use regular expressions on the HTML content. The
    202  * parameters are: what WordPress will use for the class, the Attachment ID,
    203  * image align value, and the size the image should be.
    204  *
    205  * The second filter 'get_image_tag' has the HTML content, which can then be
    206  * further manipulated by a plugin to change all attribute values and even HTML
    207  * content.
    208  *
    209  * @since 2.5.0
    210  *
    211  * @uses apply_filters() The 'get_image_tag_class' filter is the IMG element
    212  *      class attribute.
    213  * @uses apply_filters() The 'get_image_tag' filter is the full IMG element with
    214  *      all attributes.
    215  *
    216  * @param int $id Attachment ID.
    217  * @param string $alt Image Description for the alt attribute.
    218  * @param string $title Image Description for the title attribute.
    219  * @param string $align Part of the class name for aligning the image.
    220  * @param string $size Optional. Default is 'medium'.
    221  * @return string HTML IMG element for given image attachment
    222  */
    223 function get_image_tag($id, $alt, $title, $align, $size='medium') {
    224 
    225     list( $img_src, $width, $height ) = image_downsize($id, $size);
    226     $hwstring = image_hwstring($width, $height);
    227 
    228     $class = 'align' . esc_attr($align) .' size-' . esc_attr($size) . ' wp-image-' . $id;
    229     $class = apply_filters('get_image_tag_class', $class, $id, $align, $size);
    230 
    231     $html = '<img src="' . esc_attr($img_src) . '" alt="' . esc_attr($alt) . '" title="' . esc_attr($title).'" '.$hwstring.'class="'.$class.'" />';
    232 
    233     $html = apply_filters( 'get_image_tag', $html, $id, $alt, $title, $align, $size );
    234 
    235     return $html;
    236 }
    237 
    238 /**
    239  * Load an image from a string, if PHP supports it.
    240  *
    241  * @since 2.1.0
    242  *
    243  * @param string $file Filename of the image to load.
    244  * @return resource The resulting image resource on success, Error string on failure.
    245  */
    246 function wp_load_image( $file ) {
    247     if ( is_numeric( $file ) )
    248         $file = get_attached_file( $file );
    249 
    250     if ( ! file_exists( $file ) )
    251         return sprintf(__('File &#8220;%s&#8221; doesn&#8217;t exist?'), $file);
    252 
    253     if ( ! function_exists('imagecreatefromstring') )
    254         return __('The GD image library is not installed.');
    255 
    256     // Set artificially high because GD uses uncompressed images in memory
    257     @ini_set( 'memory_limit', apply_filters( 'image_memory_limit', WP_MAX_MEMORY_LIMIT ) );
    258     $image = imagecreatefromstring( file_get_contents( $file ) );
    259 
    260     if ( !is_resource( $image ) )
    261         return sprintf(__('File &#8220;%s&#8221; is not an image.'), $file);
    262 
    263     return $image;
    264 }
    265 
    266 /**
    267  * Calculates the new dimensions for a downsampled image.
    268  *
    269  * If either width or height are empty, no constraint is applied on
    270  * that dimension.
    271  *
    272  * @since 2.5.0
    273  *
    274  * @param int $current_width Current width of the image.
    275  * @param int $current_height Current height of the image.
    276  * @param int $max_width Optional. Maximum wanted width.
    277  * @param int $max_height Optional. Maximum wanted height.
    278  * @return array First item is the width, the second item is the height.
    279  */
    280 function wp_constrain_dimensions( $current_width, $current_height, $max_width=0, $max_height=0 ) {
    281     if ( !$max_width and !$max_height )
    282         return array( $current_width, $current_height );
    283 
    284     $width_ratio = $height_ratio = 1.0;
    285     $did_width = $did_height = false;
    286 
    287     if ( $max_width > 0 && $current_width > 0 && $current_width > $max_width ) {
    288         $width_ratio = $max_width / $current_width;
    289         $did_width = true;
    290     }
    291 
    292     if ( $max_height > 0 && $current_height > 0 && $current_height > $max_height ) {
    293         $height_ratio = $max_height / $current_height;
    294         $did_height = true;
    295     }
    296 
    297     // Calculate the larger/smaller ratios
    298     $smaller_ratio = min( $width_ratio, $height_ratio );
    299     $larger_ratio  = max( $width_ratio, $height_ratio );
    300 
    301     if ( intval( $current_width * $larger_ratio ) > $max_width || intval( $current_height * $larger_ratio ) > $max_height )
    302         // The larger ratio is too big. It would result in an overflow.
    303         $ratio = $smaller_ratio;
    304     else
    305         // The larger ratio fits, and is likely to be a more "snug" fit.
    306         $ratio = $larger_ratio;
    307 
    308     $w = intval( $current_width  * $ratio );
    309     $h = intval( $current_height * $ratio );
    310 
    311     // Sometimes, due to rounding, we'll end up with a result like this: 465x700 in a 177x177 box is 117x176... a pixel short
    312     // 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.
    313     // Thus we look for dimensions that are one pixel shy of the max value and bump them up
    314     if ( $did_width && $w == $max_width - 1 )
    315         $w = $max_width; // Round it up
    316     if ( $did_height && $h == $max_height - 1 )
    317         $h = $max_height; // Round it up
    318 
    319     return array( $w, $h );
    320 }
    321 
    322 /**
    323  * Retrieve calculated resized dimensions for use in imagecopyresampled().
    324  *
    325  * Calculate dimensions and coordinates for a resized image that fits within a
    326  * specified width and height. If $crop is true, the largest matching central
    327  * portion of the image will be cropped out and resized to the required size.
    328  *
    329  * @since 2.5.0
    330  * @uses apply_filters() Calls 'image_resize_dimensions' on $orig_w, $orig_h, $dest_w, $dest_h and
    331  *      $crop to provide custom resize dimensions.
    332  *
    333  * @param int $orig_w Original width.
    334  * @param int $orig_h Original height.
    335  * @param int $dest_w New width.
    336  * @param int $dest_h New height.
    337  * @param bool $crop Optional, default is false. Whether to crop image or resize.
    338  * @return bool|array False on failure. Returned array matches parameters for imagecopyresampled() PHP function.
    339  */
    340 function image_resize_dimensions($orig_w, $orig_h, $dest_w, $dest_h, $crop = false) {
    341 
    342     if ($orig_w <= 0 || $orig_h <= 0)
    343         return false;
    344     // at least one of dest_w or dest_h must be specific
    345     if ($dest_w <= 0 && $dest_h <= 0)
    346         return false;
    347 
    348     // plugins can use this to provide custom resize dimensions
    349     $output = apply_filters( 'image_resize_dimensions', null, $orig_w, $orig_h, $dest_w, $dest_h, $crop );
    350     if ( null !== $output )
    351         return $output;
    352 
    353     if ( $crop ) {
    354         // crop the largest possible portion of the original image that we can size to $dest_w x $dest_h
    355         $aspect_ratio = $orig_w / $orig_h;
    356         $new_w = min($dest_w, $orig_w);
    357         $new_h = min($dest_h, $orig_h);
    358 
    359         if ( !$new_w ) {
    360             $new_w = intval($new_h * $aspect_ratio);
    361         }
    362 
    363         if ( !$new_h ) {
    364             $new_h = intval($new_w / $aspect_ratio);
    365         }
    366 
    367         $size_ratio = max($new_w / $orig_w, $new_h / $orig_h);
    368 
    369         $crop_w = round($new_w / $size_ratio);
    370         $crop_h = round($new_h / $size_ratio);
    371 
    372         $s_x = floor( ($orig_w - $crop_w) / 2 );
    373         $s_y = floor( ($orig_h - $crop_h) / 2 );
    374     } else {
    375         // don't crop, just resize using $dest_w x $dest_h as a maximum bounding box
    376         $crop_w = $orig_w;
    377         $crop_h = $orig_h;
    378 
    379         $s_x = 0;
    380         $s_y = 0;
    381 
    382         list( $new_w, $new_h ) = wp_constrain_dimensions( $orig_w, $orig_h, $dest_w, $dest_h );
    383     }
    384 
    385     // if the resulting image would be the same size or larger we don't want to resize it
    386     if ( $new_w >= $orig_w && $new_h >= $orig_h )
    387         return false;
    388 
    389     // the return array matches the parameters to imagecopyresampled()
    390     // int dst_x, int dst_y, int src_x, int src_y, int dst_w, int dst_h, int src_w, int src_h
    391     return array( 0, 0, (int) $s_x, (int) $s_y, (int) $new_w, (int) $new_h, (int) $crop_w, (int) $crop_h );
    392 
    393 }
    394 
    395 /**
    396  * Scale down an image to fit a particular size and save a new copy of the image.
    397  *
    398  * The PNG transparency will be preserved using the function, as well as the
    399  * image type. If the file going in is PNG, then the resized image is going to
    400  * be PNG. The only supported image types are PNG, GIF, and JPEG.
    401  *
    402  * Some functionality requires API to exist, so some PHP version may lose out
    403  * support. This is not the fault of WordPress (where functionality is
    404  * downgraded, not actual defects), but of your PHP version.
    405  *
    406  * @since 2.5.0
    407  *
    408  * @param string $file Image file path.
    409  * @param int $max_w Maximum width to resize to.
    410  * @param int $max_h Maximum height to resize to.
    411  * @param bool $crop Optional. Whether to crop image or resize.
    412  * @param string $suffix Optional. File suffix.
    413  * @param string $dest_path Optional. New image file path.
    414  * @param int $jpeg_quality Optional, default is 90. Image quality percentage.
    415  * @return mixed WP_Error on failure. String with new destination path.
    416  */
    417 function image_resize( $file, $max_w, $max_h, $crop = false, $suffix = null, $dest_path = null, $jpeg_quality = 90 ) {
    418 
    419     $image = wp_load_image( $file );
    420     if ( !is_resource( $image ) )
    421         return new WP_Error( 'error_loading_image', $image, $file );
    422 
    423     $size = @getimagesize( $file );
    424     if ( !$size )
    425         return new WP_Error('invalid_image', __('Could not read image size'), $file);
    426     list($orig_w, $orig_h, $orig_type) = $size;
    427 
    428     $dims = image_resize_dimensions($orig_w, $orig_h, $max_w, $max_h, $crop);
    429     if ( !$dims )
    430         return new WP_Error( 'error_getting_dimensions', __('Could not calculate resized image dimensions') );
    431     list($dst_x, $dst_y, $src_x, $src_y, $dst_w, $dst_h, $src_w, $src_h) = $dims;
    432 
    433     $newimage = wp_imagecreatetruecolor( $dst_w, $dst_h );
    434 
    435     imagecopyresampled( $newimage, $image, $dst_x, $dst_y, $src_x, $src_y, $dst_w, $dst_h, $src_w, $src_h);
    436 
    437     // convert from full colors to index colors, like original PNG.
    438     if ( IMAGETYPE_PNG == $orig_type && function_exists('imageistruecolor') && !imageistruecolor( $image ) )
    439         imagetruecolortopalette( $newimage, false, imagecolorstotal( $image ) );
    440 
    441     // we don't need the original in memory anymore
    442     imagedestroy( $image );
    443 
    444     // $suffix will be appended to the destination filename, just before the extension
    445     if ( !$suffix )
    446         $suffix = "{$dst_w}x{$dst_h}";
    447 
    448     $info = pathinfo($file);
    449     $dir = $info['dirname'];
    450     $ext = $info['extension'];
    451     $name = wp_basename($file, ".$ext");
    452 
    453     if ( !is_null($dest_path) and $_dest_path = realpath($dest_path) )
    454         $dir = $_dest_path;
    455     $destfilename = "{$dir}/{$name}-{$suffix}.{$ext}";
    456 
    457     if ( IMAGETYPE_GIF == $orig_type ) {
    458         if ( !imagegif( $newimage, $destfilename ) )
    459             return new WP_Error('resize_path_invalid', __( 'Resize path invalid' ));
    460     } elseif ( IMAGETYPE_PNG == $orig_type ) {
    461         if ( !imagepng( $newimage, $destfilename ) )
    462             return new WP_Error('resize_path_invalid', __( 'Resize path invalid' ));
    463     } else {
    464         // all other formats are converted to jpg
    465         if ( 'jpg' != $ext && 'jpeg' != $ext )
    466             $destfilename = "{$dir}/{$name}-{$suffix}.jpg";
    467         if ( !imagejpeg( $newimage, $destfilename, apply_filters( 'jpeg_quality', $jpeg_quality, 'image_resize' ) ) )
    468             return new WP_Error('resize_path_invalid', __( 'Resize path invalid' ));
    469     }
    470 
    471     imagedestroy( $newimage );
    472 
    473     // Set correct file permissions
    474     $stat = stat( dirname( $destfilename ));
    475     $perms = $stat['mode'] & 0000666; //same permissions as parent folder, strip off the executable bits
    476     @ chmod( $destfilename, $perms );
    477 
    478     return $destfilename;
    479 }
    480 
    481 /**
    482  * Resize an image to make a thumbnail or intermediate size.
    483  *
    484  * The returned array has the file size, the image width, and image height. The
    485  * filter 'image_make_intermediate_size' can be used to hook in and change the
    486  * values of the returned array. The only parameter is the resized file path.
    487  *
    488  * @since 2.5.0
    489  *
    490  * @param string $file File path.
    491  * @param int $width Image width.
    492  * @param int $height Image height.
    493  * @param bool $crop Optional, default is false. Whether to crop image to specified height and width or resize.
    494  * @return bool|array False, if no image was created. Metadata array on success.
    495  */
    496 function image_make_intermediate_size($file, $width, $height, $crop=false) {
    497     if ( $width || $height ) {
    498         $resized_file = image_resize($file, $width, $height, $crop);
    499         if ( !is_wp_error($resized_file) && $resized_file && $info = getimagesize($resized_file) ) {
    500             $resized_file = apply_filters('image_make_intermediate_size', $resized_file);
    501             return array(
    502                 'file' => wp_basename( $resized_file ),
    503                 'width' => $info[0],
    504                 'height' => $info[1],
    505             );
    506         }
    507     }
    508     return false;
    509 }
    510 
    511 /**
    512  * Retrieve the image's intermediate size (resized) path, width, and height.
    513  *
    514  * The $size parameter can be an array with the width and height respectively.
    515  * If the size matches the 'sizes' metadata array for width and height, then it
    516  * will be used. If there is no direct match, then the nearest image size larger
    517  * than the specified size will be used. If nothing is found, then the function
    518  * will break out and return false.
    519  *
    520  * The metadata 'sizes' is used for compatible sizes that can be used for the
    521  * parameter $size value.
    522  *
    523  * The url path will be given, when the $size parameter is a string.
    524  *
    525  * If you are passing an array for the $size, you should consider using
    526  * add_image_size() so that a cropped version is generated. It's much more
    527  * efficient than having to find the closest-sized image and then having the
    528  * browser scale down the image.
    529  *
    530  * @since 2.5.0
    531  * @see add_image_size()
    532  *
    533  * @param int $post_id Attachment ID for image.
    534  * @param array|string $size Optional, default is 'thumbnail'. Size of image, either array or string.
    535  * @return bool|array False on failure or array of file path, width, and height on success.
    536  */
    537 function image_get_intermediate_size($post_id, $size='thumbnail') {
    538     if ( !is_array( $imagedata = wp_get_attachment_metadata( $post_id ) ) )
    539         return false;
    540 
    541     // get the best one for a specified set of dimensions
    542     if ( is_array($size) && !empty($imagedata['sizes']) ) {
    543         foreach ( $imagedata['sizes'] as $_size => $data ) {
    544             // already cropped to width or height; so use this size
    545             if ( ( $data['width'] == $size[0] && $data['height'] <= $size[1] ) || ( $data['height'] == $size[1] && $data['width'] <= $size[0] ) ) {
    546                 $file = $data['file'];
    547                 list($width, $height) = image_constrain_size_for_editor( $data['width'], $data['height'], $size );
    548                 return compact( 'file', 'width', 'height' );
    549             }
    550             // add to lookup table: area => size
    551             $areas[$data['width'] * $data['height']] = $_size;
    552         }
    553         if ( !$size || !empty($areas) ) {
    554             // find for the smallest image not smaller than the desired size
    555             ksort($areas);
    556             foreach ( $areas as $_size ) {
    557                 $data = $imagedata['sizes'][$_size];
    558                 if ( $data['width'] >= $size[0] || $data['height'] >= $size[1] ) {
    559                     // Skip images with unexpectedly divergent aspect ratios (crops)
    560                     // First, we calculate what size the original image would be if constrained to a box the size of the current image in the loop
    561                     $maybe_cropped = image_resize_dimensions($imagedata['width'], $imagedata['height'], $data['width'], $data['height'], false );
    562                     // 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
    563                     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'] ) ) )
    564                         continue;
    565                     // If we're still here, then we're going to use this size
    566                     $file = $data['file'];
    567                     list($width, $height) = image_constrain_size_for_editor( $data['width'], $data['height'], $size );
    568                     return compact( 'file', 'width', 'height' );
    569                 }
    570             }
    571         }
    572     }
    573 
    574     if ( is_array($size) || empty($size) || empty($imagedata['sizes'][$size]) )
    575         return false;
    576 
    577     $data = $imagedata['sizes'][$size];
    578     // include the full filesystem path of the intermediate file
    579     if ( empty($data['path']) && !empty($data['file']) ) {
    580         $file_url = wp_get_attachment_url($post_id);
    581         $data['path'] = path_join( dirname($imagedata['file']), $data['file'] );
    582         $data['url'] = path_join( dirname($file_url), $data['file'] );
    583     }
    584     return $data;
    585 }
    586 
    587 /**
    588  * Get the available image sizes
    589  * @since 3.0.0
    590  * @return array Returns a filtered array of image size strings
    591  */
    592 function get_intermediate_image_sizes() {
    593     global $_wp_additional_image_sizes;
    594     $image_sizes = array('thumbnail', 'medium', 'large'); // Standard sizes
    595     if ( isset( $_wp_additional_image_sizes ) && count( $_wp_additional_image_sizes ) )
    596         $image_sizes = array_merge( $image_sizes, array_keys( $_wp_additional_image_sizes ) );
    597 
    598     return apply_filters( 'intermediate_image_sizes', $image_sizes );
    599 }
    600 
    601 /**
    602  * Retrieve an image to represent an attachment.
    603  *
    604  * A mime icon for files, thumbnail or intermediate size for images.
    605  *
    606  * @since 2.5.0
    607  *
    608  * @param int $attachment_id Image attachment ID.
    609  * @param string $size Optional, default is 'thumbnail'.
    610  * @param bool $icon Optional, default is false. Whether it is an icon.
    611  * @return bool|array Returns an array (url, width, height), or false, if no image is available.
    612  */
    613 function wp_get_attachment_image_src($attachment_id, $size='thumbnail', $icon = false) {
    614 
    615     // get a thumbnail or intermediate image if there is one
    616     if ( $image = image_downsize($attachment_id, $size) )
    617         return $image;
    618 
    619     $src = false;
    620 
    621     if ( $icon && $src = wp_mime_type_icon($attachment_id) ) {
    622         $icon_dir = apply_filters( 'icon_dir', ABSPATH . WPINC . '/images/crystal' );
    623         $src_file = $icon_dir . '/' . wp_basename($src);
    624         @list($width, $height) = getimagesize($src_file);
    625     }
    626     if ( $src && $width && $height )
    627         return array( $src, $width, $height );
    628     return false;
    629 }
    630 
    631 /**
    632  * Get an HTML img element representing an image attachment
    633  *
    634  * While $size will accept an array, it is better to register a size with
    635  * add_image_size() so that a cropped version is generated. It's much more
    636  * efficient than having to find the closest-sized image and then having the
    637  * browser scale down the image.
    638  *
    639  * @see add_image_size()
    640  * @uses apply_filters() Calls 'wp_get_attachment_image_attributes' hook on attributes array
    641  * @uses wp_get_attachment_image_src() Gets attachment file URL and dimensions
    642  * @since 2.5.0
    643  *
    644  * @param int $attachment_id Image attachment ID.
    645  * @param string $size Optional, default is 'thumbnail'.
    646  * @param bool $icon Optional, default is false. Whether it is an icon.
    647  * @return string HTML img element or empty string on failure.
    648  */
    649 function wp_get_attachment_image($attachment_id, $size = 'thumbnail', $icon = false, $attr = '') {
    650 
    651     $html = '';
    652     $image = wp_get_attachment_image_src($attachment_id, $size, $icon);
    653     if ( $image ) {
    654         list($src, $width, $height) = $image;
    655         $hwstring = image_hwstring($width, $height);
    656         if ( is_array($size) )
    657             $size = join('x', $size);
    658         $attachment = get_post($attachment_id);
    659         $default_attr = array(
    660             'src'   => $src,
    661             'class' => "attachment-$size",
    662             'alt'   => trim(strip_tags( get_post_meta($attachment_id, '_wp_attachment_image_alt', true) )), // Use Alt field first
    663             'title' => trim(strip_tags( $attachment->post_title )),
    664         );
    665         if ( empty($default_attr['alt']) )
    666             $default_attr['alt'] = trim(strip_tags( $attachment->post_excerpt )); // If not, Use the Caption
    667         if ( empty($default_attr['alt']) )
    668             $default_attr['alt'] = trim(strip_tags( $attachment->post_title )); // Finally, use the title
    669 
    670         $attr = wp_parse_args($attr, $default_attr);
    671         $attr = apply_filters( 'wp_get_attachment_image_attributes', $attr, $attachment );
    672         $attr = array_map( 'esc_attr', $attr );
    673         $html = rtrim("<img $hwstring");
    674         foreach ( $attr as $name => $value ) {
    675             $html .= " $name=" . '"' . $value . '"';
    676         }
    677         $html .= ' />';
    678     }
    679 
    680     return $html;
    681 }
    682 
    683 /**
    684  * Adds a 'wp-post-image' class to post thumbnails
    685  * Uses the begin_fetch_post_thumbnail_html and end_fetch_post_thumbnail_html action hooks to
    686  * dynamically add/remove itself so as to only filter post thumbnails
    687  *
    688  * @since 2.9.0
    689  * @param array $attr Attributes including src, class, alt, title
    690  * @return array
    691  */
    692 function _wp_post_thumbnail_class_filter( $attr ) {
    693     $attr['class'] .= ' wp-post-image';
    694     return $attr;
    695 }
    696 
    697 /**
    698  * Adds _wp_post_thumbnail_class_filter to the wp_get_attachment_image_attributes filter
    699  *
    700  * @since 2.9.0
    701  */
    702 function _wp_post_thumbnail_class_filter_add( $attr ) {
    703     add_filter( 'wp_get_attachment_image_attributes', '_wp_post_thumbnail_class_filter' );
    704 }
    705 
    706 /**
    707  * Removes _wp_post_thumbnail_class_filter from the wp_get_attachment_image_attributes filter
    708  *
    709  * @since 2.9.0
    710  */
    711 function _wp_post_thumbnail_class_filter_remove( $attr ) {
    712     remove_filter( 'wp_get_attachment_image_attributes', '_wp_post_thumbnail_class_filter' );
    713 }
    714 
    715 add_shortcode('wp_caption', 'img_caption_shortcode');
    716 add_shortcode('caption', 'img_caption_shortcode');
    717 
    718 /**
    719  * The Caption shortcode.
    720  *
    721  * Allows a plugin to replace the content that would otherwise be returned. The
    722  * filter is 'img_caption_shortcode' and passes an empty string, the attr
    723  * parameter and the content parameter values.
    724  *
    725  * The supported attributes for the shortcode are 'id', 'align', 'width', and
    726  * 'caption'.
    727  *
    728  * @since 2.6.0
    729  *
    730  * @param array $attr Attributes attributed to the shortcode.
    731  * @param string $content Optional. Shortcode content.
    732  * @return string
    733  */
    734 function img_caption_shortcode($attr, $content = null) {
    735     // New-style shortcode with the caption inside the shortcode with the link and image tags.
    736     if ( ! isset( $attr['caption'] ) ) {
    737         if ( preg_match( '#((?:<a [^>]+>\s*)?<img [^>]+>(?:\s*</a>)?)(.*)#is', $content, $matches ) ) {
    738             $content = $matches[1];
    739             $attr['caption'] = trim( $matches[2] );
    740         }
    741     }
    742 
    743     // Allow plugins/themes to override the default caption template.
    744     $output = apply_filters('img_caption_shortcode', '', $attr, $content);
    745     if ( $output != '' )
    746         return $output;
    747 
    748     extract(shortcode_atts(array(
    749         'id'    => '',
    750         'align' => 'alignnone',
    751         'width' => '',
    752         'caption' => ''
    753     ), $attr));
    754 
    755     if ( 1 > (int) $width || empty($caption) )
    756         return $content;
    757 
    758     if ( $id ) $id = 'id="' . esc_attr($id) . '" ';
    759 
    760     return '<div ' . $id . 'class="wp-caption ' . esc_attr($align) . '" style="width: ' . (10 + (int) $width) . 'px">'
    761     . do_shortcode( $content ) . '<p class="wp-caption-text">' . $caption . '</p></div>';
    762 }
    763 
    764 add_shortcode('gallery', 'gallery_shortcode');
    765 
    766 /**
    767  * The Gallery shortcode.
    768  *
    769  * This implements the functionality of the Gallery Shortcode for displaying
    770  * WordPress images on a post.
    771  *
    772  * @since 2.5.0
    773  *
    774  * @param array $attr Attributes of the shortcode.
    775  * @return string HTML content to display gallery.
    776  */
    777 function gallery_shortcode($attr) {
    778     $post = get_post();
    779 
    780     static $instance = 0;
    781     $instance++;
    782 
    783     // Allow plugins/themes to override the default gallery template.
    784     $output = apply_filters('post_gallery', '', $attr);
    785     if ( $output != '' )
    786         return $output;
    787 
    788     // We're trusting author input, so let's at least make sure it looks like a valid orderby statement
    789     if ( isset( $attr['orderby'] ) ) {
    790         $attr['orderby'] = sanitize_sql_orderby( $attr['orderby'] );
    791         if ( !$attr['orderby'] )
    792             unset( $attr['orderby'] );
    793     }
    794 
    795     extract(shortcode_atts(array(
    796         'order'      => 'ASC',
    797         'orderby'    => 'menu_order ID',
    798         'id'         => $post->ID,
    799         'itemtag'    => 'dl',
    800         'icontag'    => 'dt',
    801         'captiontag' => 'dd',
    802         'columns'    => 3,
    803         'size'       => 'thumbnail',
    804         'ids'        => '',
    805         'include'    => '',
    806         'exclude'    => ''
    807     ), $attr));
    808 
    809     $id = intval($id);
    810     if ( 'RAND' == $order )
    811         $orderby = 'none';
    812 
    813     if ( !empty( $ids ) ) {
    814         // 'ids' is explicitly ordered
    815         $orderby = 'post__in';
    816         $include = $ids;
    817     }
    818 
    819     if ( !empty($include) ) {
    820         $_attachments = get_posts( array('include' => $include, 'post_status' => 'inherit', 'post_type' => 'attachment', 'post_mime_type' => 'image', 'order' => $order, 'orderby' => $orderby) );
    821 
    822         $attachments = array();
    823         foreach ( $_attachments as $key => $val ) {
    824             $attachments[$val->ID] = $_attachments[$key];
    825         }
    826     } elseif ( !empty($exclude) ) {
    827         $attachments = get_children( array('post_parent' => $id, 'exclude' => $exclude, 'post_status' => 'inherit', 'post_type' => 'attachment', 'post_mime_type' => 'image', 'order' => $order, 'orderby' => $orderby) );
    828     } else {
    829         $attachments = get_children( array('post_parent' => $id, 'post_status' => 'inherit', 'post_type' => 'attachment', 'post_mime_type' => 'image', 'order' => $order, 'orderby' => $orderby) );
    830     }
    831 
    832     if ( empty($attachments) )
    833         return '';
    834 
    835     if ( is_feed() ) {
    836         $output = "\n";
    837         foreach ( $attachments as $att_id => $attachment )
    838             $output .= wp_get_attachment_link($att_id, $size, true) . "\n";
    839         return $output;
    840     }
    841 
    842     $itemtag = tag_escape($itemtag);
    843     $captiontag = tag_escape($captiontag);
    844     $columns = intval($columns);
    845     $itemwidth = $columns > 0 ? floor(100/$columns) : 100;
    846     $float = is_rtl() ? 'right' : 'left';
    847 
    848     $selector = "gallery-{$instance}";
    849 
    850     $gallery_style = $gallery_div = '';
    851     if ( apply_filters( 'use_default_gallery_style', true ) )
    852         $gallery_style = "
    853         <style type='text/css'>
    854             #{$selector} {
    855                 margin: auto;
    856             }
    857             #{$selector} .gallery-item {
    858                 float: {$float};
    859                 margin-top: 10px;
    860                 text-align: center;
    861                 width: {$itemwidth}%;
    862             }
    863             #{$selector} img {
    864                 border: 2px solid #cfcfcf;
    865             }
    866             #{$selector} .gallery-caption {
    867                 margin-left: 0;
    868             }
    869         </style>
    870         <!-- see gallery_shortcode() in wp-includes/media.php -->";
    871     $size_class = sanitize_html_class( $size );
    872     $gallery_div = "<div id='$selector' class='gallery galleryid-{$id} gallery-columns-{$columns} gallery-size-{$size_class}'>";
    873     $output = apply_filters( 'gallery_style', $gallery_style . "\n\t\t" . $gallery_div );
    874 
    875     $i = 0;
    876     foreach ( $attachments as $id => $attachment ) {
    877         $link = isset($attr['link']) && 'file' == $attr['link'] ? wp_get_attachment_link($id, $size, false, false) : wp_get_attachment_link($id, $size, true, false);
    878 
    879         $output .= "<{$itemtag} class='gallery-item'>";
    880         $output .= "
    881             <{$icontag} class='gallery-icon'>
    882                 $link
    883             </{$icontag}>";
    884         if ( $captiontag && trim($attachment->post_excerpt) ) {
    885             $output .= "
    886                 <{$captiontag} class='wp-caption-text gallery-caption'>
    887                 " . wptexturize($attachment->post_excerpt) . "
    888                 </{$captiontag}>";
    889         }
    890         $output .= "</{$itemtag}>";
    891         if ( $columns > 0 && ++$i % $columns == 0 )
    892             $output .= '<br style="clear: both" />';
    893     }
    894 
    895     $output .= "
    896             <br style='clear: both;' />
    897         </div>\n";
    898 
    899     return $output;
    900 }
    901 
    902 /**
    903  * Display previous image link that has the same post parent.
    904  *
    905  * @since 2.5.0
    906  * @param string $size Optional, default is 'thumbnail'. Size of image, either array or string. 0 or 'none' will default to post_title or $text;
    907  * @param string $text Optional, default is false. If included, link will reflect $text variable.
    908  * @return string HTML content.
    909  */
    910 function previous_image_link($size = 'thumbnail', $text = false) {
    911     adjacent_image_link(true, $size, $text);
    912 }
    913 
    914 /**
    915  * Display next image link that has the same post parent.
    916  *
    917  * @since 2.5.0
    918  * @param string $size Optional, default is 'thumbnail'. Size of image, either array or string. 0 or 'none' will default to post_title or $text;
    919  * @param string $text Optional, default is false. If included, link will reflect $text variable.
    920  * @return string HTML content.
    921  */
    922 function next_image_link($size = 'thumbnail', $text = false) {
    923     adjacent_image_link(false, $size, $text);
    924 }
    925 
    926 /**
    927  * Display next or previous image link that has the same post parent.
    928  *
    929  * Retrieves the current attachment object from the $post global.
    930  *
    931  * @since 2.5.0
    932  *
    933  * @param bool $prev Optional. Default is true to display previous link, false for next.
    934  */
    935 function adjacent_image_link($prev = true, $size = 'thumbnail', $text = false) {
    936     $post = get_post();
    937     $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' ) ) );
    938 
    939     foreach ( $attachments as $k => $attachment )
    940         if ( $attachment->ID == $post->ID )
    941             break;
    942 
    943     $k = $prev ? $k - 1 : $k + 1;
    944 
    945     if ( isset($attachments[$k]) )
    946         echo wp_get_attachment_link($attachments[$k]->ID, $size, true, false, $text);
    947 }
    948 
    949 /**
    950  * Retrieve taxonomies attached to the attachment.
    951  *
    952  * @since 2.5.0
    953  *
    954  * @param int|array|object $attachment Attachment ID, Attachment data array, or Attachment data object.
    955  * @return array Empty array on failure. List of taxonomies on success.
    956  */
    957 function get_attachment_taxonomies($attachment) {
    958     if ( is_int( $attachment ) )
    959         $attachment = get_post($attachment);
    960     else if ( is_array($attachment) )
    961         $attachment = (object) $attachment;
    962 
    963     if ( ! is_object($attachment) )
    964         return array();
    965 
    966     $filename = basename($attachment->guid);
    967 
    968     $objects = array('attachment');
    969 
    970     if ( false !== strpos($filename, '.') )
    971         $objects[] = 'attachment:' . substr($filename, strrpos($filename, '.') + 1);
    972     if ( !empty($attachment->post_mime_type) ) {
    973         $objects[] = 'attachment:' . $attachment->post_mime_type;
    974         if ( false !== strpos($attachment->post_mime_type, '/') )
    975             foreach ( explode('/', $attachment->post_mime_type) as $token )
    976                 if ( !empty($token) )
    977                     $objects[] = "attachment:$token";
    978     }
    979 
    980     $taxonomies = array();
    981     foreach ( $objects as $object )
    982         if ( $taxes = get_object_taxonomies($object) )
    983             $taxonomies = array_merge($taxonomies, $taxes);
    984 
    985     return array_unique($taxonomies);
    986 }
    987 
    988 /**
    989  * Return all of the taxonomy names that are registered for attachments.
    990  *
    991  * Handles mime-type-specific taxonomies such as attachment:image and attachment:video.
    992  *
    993  * @since 3.5.0
    994  * @see get_attachment_taxonomies()
    995  * @uses get_taxonomies()
    996  *
    997  * @param string $output The type of output to return, either taxonomy 'names' or 'objects'. 'names' is the default.
    998  * @return array The names of all taxonomy of $object_type.
    999  */
    1000 function get_taxonomies_for_attachments( $output = 'names' ) {
    1001     $taxonomies = array();
    1002     foreach ( get_taxonomies( array(), 'objects' ) as $taxonomy ) {
    1003         foreach ( $taxonomy->object_type as $object_type ) {
    1004             if ( 'attachment' == $object_type || 0 === strpos( $object_type, 'attachment:' ) ) {
    1005                 if ( 'names' == $output )
    1006                     $taxonomies[] = $taxonomy->name;
    1007                 else
    1008                     $taxonomies[ $taxonomy->name ] = $taxonomy;
    1009                 break;
    1010             }
    1011         }
    1012     }
    1013 
    1014     return $taxonomies;
    1015 }
    1016 
    1017 /**
    1018  * Check if the installed version of GD supports particular image type
    1019  *
    1020  * @since 2.9.0
    1021  *
    1022  * @param string $mime_type
    1023  * @return bool
    1024  */
    1025 function gd_edit_image_support($mime_type) {
    1026     if ( function_exists('imagetypes') ) {
    1027         switch( $mime_type ) {
    1028             case 'image/jpeg':
    1029                 return (imagetypes() & IMG_JPG) != 0;
    1030             case 'image/png':
    1031                 return (imagetypes() & IMG_PNG) != 0;
    1032             case 'image/gif':
    1033                 return (imagetypes() & IMG_GIF) != 0;
    1034         }
    1035     } else {
    1036         switch( $mime_type ) {
    1037             case 'image/jpeg':
    1038                 return function_exists('imagecreatefromjpeg');
    1039             case 'image/png':
    1040                 return function_exists('imagecreatefrompng');
    1041             case 'image/gif':
    1042                 return function_exists('imagecreatefromgif');
    1043         }
    1044     }
    1045     return false;
    1046 }
    1047 
    1048 /**
    1049  * Create new GD image resource with transparency support
    1050  *
    1051  * @since 2.9.0
    1052  *
    1053  * @param int $width Image width
    1054  * @param int $height Image height
    1055  * @return image resource
    1056  */
    1057 function wp_imagecreatetruecolor($width, $height) {
    1058     $img = imagecreatetruecolor($width, $height);
    1059     if ( is_resource($img) && function_exists('imagealphablending') && function_exists('imagesavealpha') ) {
    1060         imagealphablending($img, false);
    1061         imagesavealpha($img, true);
    1062     }
    1063     return $img;
    1064 }
    1065 
    10662/**
    10673 * API for easily embedding rich media such as videos and images into content.
     
    1340276}
    1341277$GLOBALS['wp_embed'] = new WP_Embed();
    1342 
    1343 /**
    1344  * Register an embed handler. This function should probably only be used for sites that do not support oEmbed.
    1345  *
    1346  * @since 2.9.0
    1347  * @see WP_Embed::register_handler()
    1348  */
    1349 function wp_embed_register_handler( $id, $regex, $callback, $priority = 10 ) {
    1350     global $wp_embed;
    1351     $wp_embed->register_handler( $id, $regex, $callback, $priority );
    1352 }
    1353 
    1354 /**
    1355  * Unregister a previously registered embed handler.
    1356  *
    1357  * @since 2.9.0
    1358  * @see WP_Embed::unregister_handler()
    1359  */
    1360 function wp_embed_unregister_handler( $id, $priority = 10 ) {
    1361     global $wp_embed;
    1362     $wp_embed->unregister_handler( $id, $priority );
    1363 }
    1364 
    1365 /**
    1366  * Create default array of embed parameters.
    1367  *
    1368  * The width defaults to the content width as specified by the theme. If the
    1369  * theme does not specify a content width, then 500px is used.
    1370  *
    1371  * The default height is 1.5 times the width, or 1000px, whichever is smaller.
    1372  *
    1373  * The 'embed_defaults' filter can be used to adjust either of these values.
    1374  *
    1375  * @since 2.9.0
    1376  *
    1377  * @return array Default embed parameters.
    1378  */
    1379 function wp_embed_defaults() {
    1380     if ( ! empty( $GLOBALS['content_width'] ) )
    1381         $width = (int) $GLOBALS['content_width'];
    1382 
    1383     if ( empty( $width ) )
    1384         $width = 500;
    1385 
    1386     $height = min( ceil( $width * 1.5 ), 1000 );
    1387 
    1388     return apply_filters( 'embed_defaults', compact( 'width', 'height' ) );
    1389 }
    1390 
    1391 /**
    1392  * Based on a supplied width/height example, return the biggest possible dimensions based on the max width/height.
    1393  *
    1394  * @since 2.9.0
    1395  * @uses wp_constrain_dimensions() This function passes the widths and the heights.
    1396  *
    1397  * @param int $example_width The width of an example embed.
    1398  * @param int $example_height The height of an example embed.
    1399  * @param int $max_width The maximum allowed width.
    1400  * @param int $max_height The maximum allowed height.
    1401  * @return array The maximum possible width and height based on the example ratio.
    1402  */
    1403 function wp_expand_dimensions( $example_width, $example_height, $max_width, $max_height ) {
    1404     $example_width  = (int) $example_width;
    1405     $example_height = (int) $example_height;
    1406     $max_width      = (int) $max_width;
    1407     $max_height     = (int) $max_height;
    1408 
    1409     return wp_constrain_dimensions( $example_width * 1000000, $example_height * 1000000, $max_width, $max_height );
    1410 }
    1411 
    1412 /**
    1413  * Attempts to fetch the embed HTML for a provided URL using oEmbed.
    1414  *
    1415  * @since 2.9.0
    1416  * @see WP_oEmbed
    1417  *
    1418  * @uses _wp_oembed_get_object()
    1419  * @uses WP_oEmbed::get_html()
    1420  *
    1421  * @param string $url The URL that should be embedded.
    1422  * @param array $args Additional arguments and parameters.
    1423  * @return bool|string False on failure or the embed HTML on success.
    1424  */
    1425 function wp_oembed_get( $url, $args = '' ) {
    1426     require_once( ABSPATH . WPINC . '/class-oembed.php' );
    1427     $oembed = _wp_oembed_get_object();
    1428     return $oembed->get_html( $url, $args );
    1429 }
    1430 
    1431 /**
    1432  * Adds a URL format and oEmbed provider URL pair.
    1433  *
    1434  * @since 2.9.0
    1435  * @see WP_oEmbed
    1436  *
    1437  * @uses _wp_oembed_get_object()
    1438  *
    1439  * @param string $format The format of URL that this provider can handle. You can use asterisks as wildcards.
    1440  * @param string $provider The URL to the oEmbed provider.
    1441  * @param boolean $regex Whether the $format parameter is in a regex format.
    1442  */
    1443 function wp_oembed_add_provider( $format, $provider, $regex = false ) {
    1444     require_once( ABSPATH . WPINC . '/class-oembed.php' );
    1445     $oembed = _wp_oembed_get_object();
    1446     $oembed->providers[$format] = array( $provider, $regex );
    1447 }
    1448 
    1449 /**
    1450  * Removes an oEmbed provider.
    1451  *
    1452  * @since 3.5
    1453  * @see WP_oEmbed
    1454  *
    1455  * @uses _wp_oembed_get_object()
    1456  *
    1457  * @param string $format The URL format for the oEmbed provider to remove.
    1458  */
    1459 function wp_oembed_remove_provider( $format ) {
    1460     require_once( ABSPATH . WPINC . '/class-oembed.php' );
    1461 
    1462     $oembed = _wp_oembed_get_object();
    1463 
    1464     if ( isset( $oembed->providers[ $format ] ) ) {
    1465         unset( $oembed->providers[ $format ] );
    1466         return true;
    1467     }
    1468 
    1469     return false;
    1470 }
    1471 
    1472 /**
    1473  * Determines if default embed handlers should be loaded.
    1474  *
    1475  * Checks to make sure that the embeds library hasn't already been loaded. If
    1476  * it hasn't, then it will load the embeds library.
    1477  *
    1478  * @since 2.9.0
    1479  */
    1480 function wp_maybe_load_embeds() {
    1481     if ( ! apply_filters( 'load_default_embeds', true ) )
    1482         return;
    1483     wp_embed_register_handler( 'googlevideo', '#http://video\.google\.([A-Za-z.]{2,5})/videoplay\?docid=([\d-]+)(.*?)#i', 'wp_embed_handler_googlevideo' );
    1484 }
    1485 
    1486 /**
    1487  * The Google Video embed handler callback. Google Video does not support oEmbed.
    1488  *
    1489  * @see WP_Embed::register_handler()
    1490  * @see WP_Embed::shortcode()
    1491  *
    1492  * @param array $matches The regex matches from the provided regex when calling {@link wp_embed_register_handler()}.
    1493  * @param array $attr Embed attributes.
    1494  * @param string $url The original URL that was matched by the regex.
    1495  * @param array $rawattr The original unmodified attributes.
    1496  * @return string The embed HTML.
    1497  */
    1498 function wp_embed_handler_googlevideo( $matches, $attr, $url, $rawattr ) {
    1499     // If the user supplied a fixed width AND height, use it
    1500     if ( !empty($rawattr['width']) && !empty($rawattr['height']) ) {
    1501         $width  = (int) $rawattr['width'];
    1502         $height = (int) $rawattr['height'];
    1503     } else {
    1504         list( $width, $height ) = wp_expand_dimensions( 425, 344, $attr['width'], $attr['height'] );
    1505     }
    1506 
    1507     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 );
    1508 }
    1509 
    1510 /**
    1511  * Prints default plupload arguments.
    1512  *
    1513  * @since 3.4.0
    1514  */
    1515 function wp_plupload_default_settings() {
    1516     global $wp_scripts;
    1517 
    1518     $max_upload_size = wp_max_upload_size();
    1519 
    1520     $defaults = array(
    1521         'runtimes'            => 'html5,silverlight,flash,html4',
    1522         'file_data_name'      => 'async-upload', // key passed to $_FILE.
    1523         'multiple_queues'     => true,
    1524         'max_file_size'       => $max_upload_size . 'b',
    1525         'url'                 => admin_url( 'admin-ajax.php', 'relative' ),
    1526         'flash_swf_url'       => includes_url( 'js/plupload/plupload.flash.swf' ),
    1527         'silverlight_xap_url' => includes_url( 'js/plupload/plupload.silverlight.xap' ),
    1528         'filters'             => array( array( 'title' => __( 'Allowed Files' ), 'extensions' => '*') ),
    1529         'multipart'           => true,
    1530         'urlstream_upload'    => true,
    1531     );
    1532 
    1533     $defaults = apply_filters( 'plupload_default_settings', $defaults );
    1534 
    1535     $params = array(
    1536         'action' => 'upload-attachment',
    1537     );
    1538 
    1539     $params = apply_filters( 'plupload_default_params', $params );
    1540     $params['_wpnonce'] = wp_create_nonce( 'media-form' );
    1541     $defaults['multipart_params'] = $params;
    1542 
    1543     $settings = array(
    1544         'defaults' => $defaults,
    1545         'browser'  => array(
    1546             'mobile'    => wp_is_mobile(),
    1547             'supported' => _device_can_upload(),
    1548         ),
    1549     );
    1550 
    1551     $script = 'var _wpPluploadSettings = ' . json_encode( $settings ) . ';';
    1552 
    1553     $data = $wp_scripts->get_data( 'wp-plupload', 'data' );
    1554     if ( $data )
    1555         $script = "$data\n$script";
    1556 
    1557     $wp_scripts->add_data( 'wp-plupload', 'data', $script );
    1558 }
    1559 add_action( 'customize_controls_enqueue_scripts', 'wp_plupload_default_settings' );
    1560 
    1561 
    1562 /**
    1563  * Prepares an attachment post object for JS, where it is expected
    1564  * to be JSON-encoded and fit into an Attachment model.
    1565  *
    1566  * @since 3.5.0
    1567  *
    1568  * @param mixed $attachment Attachment ID or object.
    1569  * @return array Array of attachment details.
    1570  */
    1571 function wp_prepare_attachment_for_js( $attachment ) {
    1572     if ( ! $attachment = get_post( $attachment ) )
    1573        return;
    1574 
    1575     if ( 'attachment' != $attachment->post_type )
    1576        return;
    1577 
    1578     $meta = wp_get_attachment_metadata( $attachment->ID );
    1579     list( $type, $subtype ) = explode( '/', $attachment->post_mime_type );
    1580 
    1581     $attachment_url = wp_get_attachment_url( $attachment->ID );
    1582 
    1583     $response = array(
    1584         'id'          => $attachment->ID,
    1585         'title'       => $attachment->post_title,
    1586         'filename'    => basename( $attachment->guid ),
    1587         'url'         => $attachment_url,
    1588         'alt'         => get_post_meta( $attachment->ID, '_wp_attachment_image_alt', true ),
    1589         'author'      => $attachment->post_author,
    1590         'description' => $attachment->post_content,
    1591         'caption'     => $attachment->post_excerpt,
    1592         'name'        => $attachment->post_name,
    1593         'status'      => $attachment->post_status,
    1594         'uploadedTo'  => $attachment->post_parent,
    1595         'date'        => strtotime( $attachment->post_date_gmt ) * 1000,
    1596         'modified'    => strtotime( $attachment->post_modified_gmt ) * 1000,
    1597         'mime'        => $attachment->post_mime_type,
    1598         'type'        => $type,
    1599         'subtype'     => $subtype,
    1600         'icon'        => wp_mime_type_icon( $attachment->post_mime_type ),
    1601     );
    1602 
    1603     if ( $meta && 'image' === $type ) {
    1604         $sizes = array();
    1605         $base_url = str_replace( wp_basename( $attachment_url ), '', $attachment_url );
    1606 
    1607         if ( isset( $meta['sizes'] ) ) {
    1608             foreach ( $meta['sizes'] as $slug => $size ) {
    1609                 $sizes[ $slug ] = array(
    1610                     'height'      => $size['height'],
    1611                     'width'       => $size['width'],
    1612                     'url'         => $base_url . $size['file'],
    1613                     'orientation' => $size['height'] > $size['width'] ? 'portrait' : 'landscape',
    1614                 );
    1615             }
    1616         }
    1617 
    1618         $response = array_merge( $response, array(
    1619             'height'      => $meta['height'],
    1620             'width'       => $meta['width'],
    1621             'sizes'       => $sizes,
    1622             'orientation' => $meta['height'] > $meta['width'] ? 'portrait' : 'landscape',
    1623         ) );
    1624     }
    1625 
    1626     return apply_filters( 'wp_prepare_attachment_for_js', $response, $attachment, $meta );
    1627 }
    1628 
    1629 /**
    1630  * Prints the templates used in the media manager.
    1631  *
    1632  * @since 3.5.0
    1633  */
    1634 function wp_print_media_templates( $attachment ) {
    1635     ?>
    1636     <script type="text/html" id="tmpl-media-modal">
    1637         <div class="media-modal">
    1638             <div class="media-modal-header">
    1639                 <h3><%- title %></h3>
    1640                 <a class="media-modal-close" href="" title="<?php esc_attr_e('Close'); ?>"><?php echo 'Close'; ?></a>
    1641             </div>
    1642             <div class="media-modal-content"></div>
    1643         </div>
    1644         <div class="media-modal-backdrop"></div>
    1645     </script>
    1646 
    1647     <script type="text/html" id="tmpl-media-workspace">
    1648         <div class="upload-attachments">
    1649             <% if ( selectOne ) { %>
    1650                 <h3><?php _e( 'Drop a file here' ); ?></h3>
    1651                 <span><?php _ex( 'or', 'Uploader: Drop a file here - or - Select a File' ); ?></span>
    1652                 <a href="#" class="button-secondary"><?php _e( 'Select a File' ); ?></a>
    1653             <% } else { %>
    1654                 <h3><?php _e( 'Drop files here' ); ?></h3>
    1655                 <span><?php _ex( 'or', 'Uploader: Drop files here - or - Select Files' ); ?></span>
    1656                 <a href="#" class="button-secondary"><?php _e( 'Select Files' ); ?></a>
    1657             <% } %>
    1658 
    1659             <div class="media-progress-bar"><div></div></div>
    1660         </div>
    1661     </script>
    1662 
    1663     <script type="text/html" id="tmpl-attachments">
    1664         <div class="attachments-header">
    1665             <h3><%- directions %></h3>
    1666             <input class="search" type="text" placeholder="<?php esc_attr_e('Search'); ?>" />
    1667         </div>
    1668     </script>
    1669 
    1670     <script type="text/html" id="tmpl-attachment">
    1671         <div class="attachment-preview type-<%- type %> subtype-<%- subtype %> <%- orientation %>">
    1672             <% if ( thumbnail ) { %>
    1673                 <img src="<%- thumbnail %>" draggable="false" />
    1674             <% } %>
    1675 
    1676             <% if ( uploading ) { %>
    1677                 <div class="media-progress-bar"><div></div></div>
    1678             <% } %>
    1679             <div class="actions"></div>
    1680         </div>
    1681         <div class="describe"></div>
    1682     </script>
    1683 
    1684     <script type="text/html" id="tmpl-media-selection-preview">
    1685         <div class="selected-img selected-count-<%- count %>">
    1686             <% if ( thumbnail ) { %>
    1687                 <img src="<%- thumbnail %>" draggable="false" />
    1688             <% } %>
    1689 
    1690             <span class="count"><%- count %></span>
    1691         </div>
    1692         <a class="clear-selection" href="#"><?php _e('Clear selection'); ?></a>
    1693     </script>
    1694     <?php
    1695 }
  • trunk/wp-includes/media.php

    r21998 r21999  
    10651065
    10661066/**
    1067  * API for easily embedding rich media such as videos and images into content.
    1068  *
    1069  * @package WordPress
    1070  * @subpackage Embed
    1071  * @since 2.9.0
    1072  */
    1073 class WP_Embed {
    1074     var $handlers = array();
    1075     var $post_ID;
    1076     var $usecache = true;
    1077     var $linkifunknown = true;
    1078 
    1079     /**
    1080      * Constructor
    1081      */
    1082     function __construct() {
    1083         // Hack to get the [embed] shortcode to run before wpautop()
    1084         add_filter( 'the_content', array( $this, 'run_shortcode' ), 8 );
    1085 
    1086         // Shortcode placeholder for strip_shortcodes()
    1087         add_shortcode( 'embed', '__return_false' );
    1088 
    1089         // Attempts to embed all URLs in a post
    1090         add_filter( 'the_content', array( $this, 'autoembed' ), 8 );
    1091 
    1092         // After a post is saved, invalidate the oEmbed cache
    1093         add_action( 'save_post', array( $this, 'delete_oembed_caches' ) );
    1094 
    1095         // After a post is saved, cache oEmbed items via AJAX
    1096         add_action( 'edit_form_advanced', array( $this, 'maybe_run_ajax_cache' ) );
    1097     }
    1098 
    1099     /**
    1100      * Process the [embed] shortcode.
    1101      *
    1102      * Since the [embed] shortcode needs to be run earlier than other shortcodes,
    1103      * this function removes all existing shortcodes, registers the [embed] shortcode,
    1104      * calls {@link do_shortcode()}, and then re-registers the old shortcodes.
    1105      *
    1106      * @uses $shortcode_tags
    1107      * @uses remove_all_shortcodes()
    1108      * @uses add_shortcode()
    1109      * @uses do_shortcode()
    1110      *
    1111      * @param string $content Content to parse
    1112      * @return string Content with shortcode parsed
    1113      */
    1114     function run_shortcode( $content ) {
    1115         global $shortcode_tags;
    1116 
    1117         // Back up current registered shortcodes and clear them all out
    1118         $orig_shortcode_tags = $shortcode_tags;
    1119         remove_all_shortcodes();
    1120 
    1121         add_shortcode( 'embed', array( $this, 'shortcode' ) );
    1122 
    1123         // Do the shortcode (only the [embed] one is registered)
    1124         $content = do_shortcode( $content );
    1125 
    1126         // Put the original shortcodes back
    1127         $shortcode_tags = $orig_shortcode_tags;
    1128 
    1129         return $content;
    1130     }
    1131 
    1132     /**
    1133      * If a post/page was saved, then output JavaScript to make
    1134      * an AJAX request that will call WP_Embed::cache_oembed().
    1135      */
    1136     function maybe_run_ajax_cache() {
    1137         $post = get_post();
    1138 
    1139         if ( ! $post || empty($_GET['message']) || 1 != $_GET['message'] )
    1140             return;
    1141 
    1142 ?>
    1143 <script type="text/javascript">
    1144 /* <![CDATA[ */
    1145     jQuery(document).ready(function($){
    1146         $.get("<?php echo admin_url( 'admin-ajax.php?action=oembed-cache&post=' . $post->ID, 'relative' ); ?>");
    1147     });
    1148 /* ]]> */
    1149 </script>
    1150 <?php
    1151     }
    1152 
    1153     /**
    1154      * Register an embed handler. Do not use this function directly, use {@link wp_embed_register_handler()} instead.
    1155      * This function should probably also only be used for sites that do not support oEmbed.
    1156      *
    1157      * @param string $id An internal ID/name for the handler. Needs to be unique.
    1158      * @param string $regex The regex that will be used to see if this handler should be used for a URL.
    1159      * @param callback $callback The callback function that will be called if the regex is matched.
    1160      * @param int $priority Optional. Used to specify the order in which the registered handlers will be tested (default: 10). Lower numbers correspond with earlier testing, and handlers with the same priority are tested in the order in which they were added to the action.
    1161      */
    1162     function register_handler( $id, $regex, $callback, $priority = 10 ) {
    1163         $this->handlers[$priority][$id] = array(
    1164             'regex'    => $regex,
    1165             'callback' => $callback,
    1166         );
    1167     }
    1168 
    1169     /**
    1170      * Unregister a previously registered embed handler. Do not use this function directly, use {@link wp_embed_unregister_handler()} instead.
    1171      *
    1172      * @param string $id The handler ID that should be removed.
    1173      * @param int $priority Optional. The priority of the handler to be removed (default: 10).
    1174      */
    1175     function unregister_handler( $id, $priority = 10 ) {
    1176         if ( isset($this->handlers[$priority][$id]) )
    1177             unset($this->handlers[$priority][$id]);
    1178     }
    1179 
    1180     /**
    1181      * The {@link do_shortcode()} callback function.
    1182      *
    1183      * Attempts to convert a URL into embed HTML. Starts by checking the URL against the regex of the registered embed handlers.
    1184      * If none of the regex matches and it's enabled, then the URL will be given to the {@link WP_oEmbed} class.
    1185      *
    1186      * @uses wp_oembed_get()
    1187      * @uses wp_parse_args()
    1188      * @uses wp_embed_defaults()
    1189      * @uses WP_Embed::maybe_make_link()
    1190      * @uses get_option()
    1191      * @uses author_can()
    1192      * @uses wp_cache_get()
    1193      * @uses wp_cache_set()
    1194      * @uses get_post_meta()
    1195      * @uses update_post_meta()
    1196      *
    1197      * @param array $attr Shortcode attributes.
    1198      * @param string $url The URL attempting to be embedded.
    1199      * @return string The embed HTML on success, otherwise the original URL.
    1200      */
    1201     function shortcode( $attr, $url = '' ) {
    1202         $post = get_post();
    1203 
    1204         if ( empty( $url ) )
    1205             return '';
    1206 
    1207         $rawattr = $attr;
    1208         $attr = wp_parse_args( $attr, wp_embed_defaults() );
    1209 
    1210         // kses converts & into &amp; and we need to undo this
    1211         // See http://core.trac.wordpress.org/ticket/11311
    1212         $url = str_replace( '&amp;', '&', $url );
    1213 
    1214         // Look for known internal handlers
    1215         ksort( $this->handlers );
    1216         foreach ( $this->handlers as $priority => $handlers ) {
    1217             foreach ( $handlers as $id => $handler ) {
    1218                 if ( preg_match( $handler['regex'], $url, $matches ) && is_callable( $handler['callback'] ) ) {
    1219                     if ( false !== $return = call_user_func( $handler['callback'], $matches, $attr, $url, $rawattr ) )
    1220                         return apply_filters( 'embed_handler_html', $return, $url, $attr );
    1221                 }
    1222             }
    1223         }
    1224 
    1225         $post_ID = ( ! empty( $post->ID ) ) ? $post->ID : null;
    1226         if ( ! empty( $this->post_ID ) ) // Potentially set by WP_Embed::cache_oembed()
    1227             $post_ID = $this->post_ID;
    1228 
    1229         // Unknown URL format. Let oEmbed have a go.
    1230         if ( $post_ID ) {
    1231 
    1232             // Check for a cached result (stored in the post meta)
    1233             $cachekey = '_oembed_' . md5( $url . serialize( $attr ) );
    1234             if ( $this->usecache ) {
    1235                 $cache = get_post_meta( $post_ID, $cachekey, true );
    1236 
    1237                 // Failures are cached
    1238                 if ( '{{unknown}}' === $cache )
    1239                     return $this->maybe_make_link( $url );
    1240 
    1241                 if ( ! empty( $cache ) )
    1242                     return apply_filters( 'embed_oembed_html', $cache, $url, $attr, $post_ID );
    1243             }
    1244 
    1245             // Use oEmbed to get the HTML
    1246             $attr['discover'] = ( apply_filters('embed_oembed_discover', false) && author_can( $post_ID, 'unfiltered_html' ) );
    1247             $html = wp_oembed_get( $url, $attr );
    1248 
    1249             // Cache the result
    1250             $cache = ( $html ) ? $html : '{{unknown}}';
    1251             update_post_meta( $post_ID, $cachekey, $cache );
    1252 
    1253             // If there was a result, return it
    1254             if ( $html )
    1255                 return apply_filters( 'embed_oembed_html', $html, $url, $attr, $post_ID );
    1256         }
    1257 
    1258         // Still unknown
    1259         return $this->maybe_make_link( $url );
    1260     }
    1261 
    1262     /**
    1263      * Delete all oEmbed caches.
    1264      *
    1265      * @param int $post_ID Post ID to delete the caches for.
    1266      */
    1267     function delete_oembed_caches( $post_ID ) {
    1268         $post_metas = get_post_custom_keys( $post_ID );
    1269         if ( empty($post_metas) )
    1270             return;
    1271 
    1272         foreach( $post_metas as $post_meta_key ) {
    1273             if ( '_oembed_' == substr( $post_meta_key, 0, 8 ) )
    1274                 delete_post_meta( $post_ID, $post_meta_key );
    1275         }
    1276     }
    1277 
    1278     /**
    1279      * Triggers a caching of all oEmbed results.
    1280      *
    1281      * @param int $post_ID Post ID to do the caching for.
    1282      */
    1283     function cache_oembed( $post_ID ) {
    1284         $post = get_post( $post_ID );
    1285 
    1286         if ( empty($post->ID) || !in_array( $post->post_type, apply_filters( 'embed_cache_oembed_types', array( 'post', 'page' ) ) ) )
    1287             return;
    1288 
    1289         // Trigger a caching
    1290         if ( !empty($post->post_content) ) {
    1291             $this->post_ID = $post->ID;
    1292             $this->usecache = false;
    1293 
    1294             $content = $this->run_shortcode( $post->post_content );
    1295             $this->autoembed( $content );
    1296 
    1297             $this->usecache = true;
    1298         }
    1299     }
    1300 
    1301     /**
    1302      * Passes any unlinked URLs that are on their own line to {@link WP_Embed::shortcode()} for potential embedding.
    1303      *
    1304      * @uses WP_Embed::autoembed_callback()
    1305      *
    1306      * @param string $content The content to be searched.
    1307      * @return string Potentially modified $content.
    1308      */
    1309     function autoembed( $content ) {
    1310         return preg_replace_callback( '|^\s*(https?://[^\s"]+)\s*$|im', array( $this, 'autoembed_callback' ), $content );
    1311     }
    1312 
    1313     /**
    1314      * Callback function for {@link WP_Embed::autoembed()}.
    1315      *
    1316      * @uses WP_Embed::shortcode()
    1317      *
    1318      * @param array $match A regex match array.
    1319      * @return string The embed HTML on success, otherwise the original URL.
    1320      */
    1321     function autoembed_callback( $match ) {
    1322         $oldval = $this->linkifunknown;
    1323         $this->linkifunknown = false;
    1324         $return = $this->shortcode( array(), $match[1] );
    1325         $this->linkifunknown = $oldval;
    1326 
    1327         return "\n$return\n";
    1328     }
    1329 
    1330     /**
    1331      * Conditionally makes a hyperlink based on an internal class variable.
    1332      *
    1333      * @param string $url URL to potentially be linked.
    1334      * @return string Linked URL or the original URL.
    1335      */
    1336     function maybe_make_link( $url ) {
    1337         $output = ( $this->linkifunknown ) ? '<a href="' . esc_attr($url) . '">' . esc_html($url) . '</a>' : $url;
    1338         return apply_filters( 'embed_maybe_make_link', $output, $url );
    1339     }
    1340 }
    1341 $GLOBALS['wp_embed'] = new WP_Embed();
    1342 
    1343 /**
    13441067 * Register an embed handler. This function should probably only be used for sites that do not support oEmbed.
    13451068 *
  • trunk/wp-settings.php

    r21544 r21999  
    135135require( ABSPATH . WPINC . '/canonical.php' );
    136136require( ABSPATH . WPINC . '/shortcodes.php' );
     137require( ABSPATH . WPINC . '/class-wp-embed.php' );
    137138require( ABSPATH . WPINC . '/media.php' );
    138139require( ABSPATH . WPINC . '/http.php' );
Note: See TracChangeset for help on using the changeset viewer.