Make WordPress Core

Ticket #23725: 23725-combined.diff

File 23725-combined.diff, 49.2 KB (added by wonderboymusic, 11 years ago)
  • wp-admin/css/wp-admin.css

    diff --git wp-admin/css/wp-admin.css wp-admin/css/wp-admin.css
    index 4959ad2..98b237e 100644
    table.fixed { 
    24252425
    24262426.fixed .column-date,
    24272427.fixed .column-parent,
    2428 .fixed .column-links {
     2428.fixed .column-links,
     2429.fixed .column-format,
     2430.fixed .column-author {
    24292431        width: 10%;
    24302432}
    24312433
    2432 .fixed .column-response,
    2433 .fixed .column-author,
    24342434.fixed .column-categories,
    2435 .fixed .column-tags,
     2435.fixed .column-tags {
     2436        width: 12.5%;
     2437}
     2438
     2439.fixed .column-response,
    24362440.fixed .column-rel,
    24372441.fixed .column-role {
    24382442        width: 15%;
    24392443}
    24402444
    24412445.fixed .column-comments {
    2442         width: 4em;
     2446        width: 3em;
    24432447        padding: 8px 0;
    24442448        text-align: left;
    24452449}
  • wp-admin/edit-form-advanced.php

    diff --git wp-admin/edit-form-advanced.php wp-admin/edit-form-advanced.php
    index 744f3b2..aa4c29c 100644
    if ( post_type_supports( $post_type, 'post-formats' ) ) { 
    141141if ( post_type_supports($post_type, 'page-attributes') )
    142142        add_meta_box('pageparentdiv', 'page' == $post_type ? __('Page Attributes') : __('Attributes'), 'page_attributes_meta_box', null, 'side', 'core');
    143143
    144 if ( current_theme_supports( 'post-thumbnails', $post_type ) && post_type_supports( $post_type, 'thumbnail' ) )
    145                 add_meta_box('postimagediv', __('Featured Image'), 'post_thumbnail_meta_box', null, 'side', 'low');
     144$audio_post_support = $video_post_support = false;
     145$theme_support = current_theme_supports( 'post-thumbnails', $post_type ) && post_type_supports( $post_type, 'thumbnail' );
     146if ( 'attachment' === $post_type && ! empty( $post->post_mime_type ) ) {
     147        $audio_post_support = 0 === strpos( $post->post_mime_type, 'audio/' ) && current_theme_supports( 'post-thumbnails', 'attachment:audio' ) && post_type_supports( 'attachment:audio', 'thumbnail' );
     148        $video_post_support = 0 === strpos( $post->post_mime_type, 'video/' ) && current_theme_supports( 'post-thumbnails', 'attachment:video' ) && post_type_supports( 'attachment:video', 'thumbnail' );
     149}
     150
     151if ( $theme_support || $audio_post_support || $video_post_support )
     152        add_meta_box('postimagediv', __('Featured Image'), 'post_thumbnail_meta_box', null, 'side', 'low');
    146153
    147154if ( post_type_supports($post_type, 'excerpt') )
    148155        add_meta_box('postexcerpt', __('Excerpt'), 'post_excerpt_meta_box', null, 'normal', 'core');
    if ( post_type_supports( $post_type, 'post-formats' ) ) { 
    343350                else
    344351                        $class = 'nav-tab';
    345352
    346                 echo '<a class="' . $class . '" href="?format=' . $slug . '" data-wp-format="' . $slug . '">' . $label . '</a>';
     353                echo '<a id="' . $slug . '" class="' . $class . '" href="?format=' . $slug . '" data-wp-format="' . $slug . '">' . $label . '</a>';
    347354        }
    348355
    349356        echo '</h2>';
  • wp-admin/includes/ajax-actions.php

    diff --git wp-admin/includes/ajax-actions.php wp-admin/includes/ajax-actions.php
    index 6d58765..57c8080 100644
    function wp_ajax_send_attachment_to_editor() { 
    20192019                $caption = isset( $attachment['post_excerpt'] ) ? $attachment['post_excerpt'] : '';
    20202020                $title = ''; // We no longer insert title tags into <img> tags, as they are redundant.
    20212021                $html = get_image_send_to_editor( $id, $caption, $title, $align, $url, (bool) $rel, $size, $alt );
     2022        } elseif ( 'video' === substr( $post->post_mime_type, 0, 5 ) || 'audio' === substr( $post->post_mime_type, 0, 5 )  ) {
     2023                $html = stripslashes_deep( $_POST['html'] );
    20222024        }
    20232025
    20242026        $html = apply_filters( 'media_send_to_editor', $html, $id, $attachment );
  • wp-admin/includes/class-wp-posts-list-table.php

    diff --git wp-admin/includes/class-wp-posts-list-table.php wp-admin/includes/class-wp-posts-list-table.php
    index 996dc4f..ed9efb1 100644
    class WP_Posts_List_Table extends WP_List_Table { 
    214214                                );
    215215                                wp_dropdown_categories( $dropdown_options );
    216216                        }
     217
     218                        if ( post_type_supports( $this->screen->post_type, 'post-formats' ) ) {
     219                                $dropdown_options = array(
     220                                        'show_option_all' => __( 'View all formats' ),
     221                                        'orderby' => 'name',
     222                                        'name' => 'format',
     223                                        'taxonomy' => 'post_format',
     224                                        'selected' => isset( $_GET['format'] ) ? $_GET['format'] : 0,
     225+                                       'hide_if_empty' => true
     226                                );
     227
     228                                wp_dropdown_categories( $dropdown_options );
     229                        }
     230
    217231                        do_action( 'restrict_manage_posts' );
    218232                        submit_button( __( 'Filter' ), 'button', false, false, array( 'id' => 'post-query-submit' ) );
    219233                }
  • wp-admin/includes/image.php

    diff --git wp-admin/includes/image.php wp-admin/includes/image.php
    index 08d4c45..f2e636b 100644
    function wp_generate_attachment_metadata( $attachment_id, $file ) { 
    7373        $attachment = get_post( $attachment_id );
    7474
    7575        $metadata = array();
     76        $support = false;
    7677        if ( preg_match('!^image/!', get_post_mime_type( $attachment )) && file_is_displayable_image($file) ) {
    7778                $imagesize = getimagesize( $file );
    7879                $metadata['width'] = $imagesize[0];
    function wp_generate_attachment_metadata( $attachment_id, $file ) { 
    117118                if ( $image_meta )
    118119                        $metadata['image_meta'] = $image_meta;
    119120
     121        } elseif ( preg_match( '#^video/#', get_post_mime_type( $attachment ) ) ) {
     122                $metadata = wp_read_video_metadata( $file );
     123                $support = current_theme_supports( 'post-thumbnails', 'attachment:video' ) && post_type_supports( 'attachment:video', 'thumbnail' );
     124        } elseif ( preg_match( '#^audio/#', get_post_mime_type( $attachment ) ) ) {
     125                $metadata = wp_read_audio_metadata( $file );
     126                $support = current_theme_supports( 'post-thumbnails', 'attachment:audio' ) && post_type_supports( 'attachment:audio', 'thumbnail' );
    120127        }
    121128
     129        if ( $support && ! empty( $metadata['image']['data'] ) ) {
     130                $ext = '.jpg';
     131                switch ( $metadata['image']['mime'] ) {
     132                case 'image/gif':
     133                        $ext = '.gif';
     134                        break;
     135                case 'image/png':
     136                        $ext = '.png';
     137                        break;
     138                }
     139                $basename = str_replace( '.', '-', basename( $file ) ) . '-image' . $ext;
     140                $uploaded = wp_upload_bits( $basename, '', $metadata['image']['data'] );
     141                if ( false === $uploaded['error'] ) {
     142                        $attachment = array(
     143                                'post_mime_type' => $metadata['image']['mime'],
     144                                'post_type' => 'attachment',
     145                                'post_content' => '',
     146                        );
     147                        $sub_attachment_id = wp_insert_attachment( $attachment, $uploaded['file'] );
     148                        $attach_data = wp_generate_attachment_metadata( $sub_attachment_id, $uploaded['file'] );
     149                        wp_update_attachment_metadata( $sub_attachment_id, $attach_data );
     150                        update_post_meta( $attachment_id, '_thumbnail_id', $sub_attachment_id );
     151                }
     152        }
     153        // remove the blob of binary data from the array
     154        unset( $metadata['image']['data'] );
     155
    122156        return apply_filters( 'wp_generate_attachment_metadata', $metadata, $attachment_id );
    123157}
    124158
  • wp-admin/includes/media.php

    diff --git wp-admin/includes/media.php wp-admin/includes/media.php
    index c58b2d7..75aed1f 100644
    function edit_form_image_editor() { 
    22852285        $title = esc_attr( $post->post_title );
    22862286        $alt_text = get_post_meta( $post->ID, '_wp_attachment_image_alt', true );
    22872287
    2288         $att_url = wp_get_attachment_url( $post->ID );
    2289 
     2288        $att_url = wp_get_attachment_url( $post->ID ); ?>
     2289        <div class="wp_attachment_holder">
     2290        <?php
    22902291        if ( wp_attachment_is_image( $post->ID ) ) :
    22912292                $image_edit_button = '';
    22922293                if ( wp_image_editor_supports( array( 'mime_type' => $post->post_mime_type ) ) ) {
    function edit_form_image_editor() { 
    22942295                        $image_edit_button = "<input type='button' id='imgedit-open-btn-$post->ID' onclick='imageEdit.open( $post->ID, \"$nonce\" )' class='button' value='" . esc_attr__( 'Edit Image' ) . "' /> <span class='spinner'></span>";
    22952296                }
    22962297        ?>
    2297         <div class="wp_attachment_holder">
     2298
    22982299                <div class="imgedit-response" id="imgedit-response-<?php echo $attachment_id; ?>"></div>
    22992300
    23002301                <div<?php if ( $open ) echo ' style="display:none"'; ?> class="wp_attachment_image" id="media-head-<?php echo $attachment_id; ?>">
    function edit_form_image_editor() { 
    23042305                <div<?php if ( ! $open ) echo ' style="display:none"'; ?> class="image-editor" id="image-editor-<?php echo $attachment_id; ?>">
    23052306                        <?php if ( $open ) wp_image_editor( $attachment_id ); ?>
    23062307                </div>
    2307         </div>
    2308         <?php endif; ?>
     2308        <?php
     2309        elseif ( $attachment_id && 0 === strpos( $post->post_mime_type, 'audio/' ) ):
     2310
     2311                echo do_shortcode( '[audio src="' . $att_url . '"]' );
     2312
     2313        elseif ( $attachment_id && 0 === strpos( $post->post_mime_type, 'video/' ) ):
     2314
     2315                $meta = wp_get_attachment_metadata( $attachment_id );
     2316                $shortcode = sprintf( '[video src="%s" width="%d" height="%d"]',
     2317                        $att_url,
     2318                        $meta['width'],
     2319                        $meta['height']
     2320                );
     2321                echo do_shortcode( $shortcode );
    23092322
     2323        endif; ?>
     2324        </div>
    23102325        <div class="wp_attachment_details edit-form-section">
    23112326                <p>
    23122327                        <label for="attachment_caption"><strong><?php _e( 'Caption' ); ?></strong></label><br />
    add_filter( 'media_upload_gallery', 'media_upload_gallery' ); 
    23972412add_filter( 'media_upload_library', 'media_upload_library' );
    23982413
    23992414add_action( 'attachment_submitbox_misc_actions', 'attachment_submitbox_metadata' );
     2415
     2416/**
     2417 * Parse ID3v2, ID3v1, and getID3 comments to extract usable data
     2418 *
     2419 * @since 3.6.0
     2420 *
     2421 * @param array $metadata An existing array with data
     2422 * @param array $data Data supplied by ID3 tags
     2423 */
     2424function wp_add_id3_tag_data( &$metadata, $data ) {
     2425        foreach ( array( 'id3v2', 'id3v1' ) as $version ) {
     2426                if ( ! empty( $data[$version]['comments'] ) ) {
     2427                        foreach ( $data[$version]['comments'] as $key => $list ) {
     2428                                if ( ! empty( $list ) ) {
     2429                                        $metadata[$key] = reset( $list );
     2430                                        // fix bug in byte stream analysis
     2431                                        if ( 'terms_of_use' === $key && 0 === strpos( $metadata[$key], 'yright notice.' ) )
     2432                                                $metadata[$key] = 'Cop' . $metadata[$key];
     2433                                }
     2434                        }
     2435                        break;
     2436                }
     2437        }
     2438
     2439        if ( ! empty( $data['id3v2']['APIC'] ) ) {
     2440                $image = reset( $data['id3v2']['APIC']);
     2441                if ( ! empty( $image['data'] ) ) {
     2442                        $metadata['image'] = array(
     2443                                'data' => $image['data'],
     2444                                'mime' => $image['image_mime'],
     2445                                'width' => $image['image_width'],
     2446                                'height' => $image['image_height']
     2447                        );
     2448                }
     2449        } elseif ( ! empty( $data['comments']['picture'] ) ) {
     2450                $image = reset( $data['comments']['picture'] );
     2451                if ( ! empty( $image['data'] ) ) {
     2452                        $metadata['image'] = array(
     2453                                'data' => $image['data'],
     2454                                'mime' => $image['image_mime']
     2455                        );
     2456                }
     2457        }
     2458}
     2459
     2460/**
     2461 * Retrieve metadata from a video file's ID3 tags
     2462 *
     2463 * @since 3.6.0
     2464 *
     2465 * @param string $file Path to file.
     2466 * @return array|boolean Returns array of metadata, if found.
     2467 */
     2468function wp_read_video_metadata( $file ) {
     2469        if ( ! file_exists( $file ) )
     2470                return false;
     2471
     2472        $metadata = array();
     2473
     2474        if ( ! class_exists( 'getID3' ) )
     2475                require( ABSPATH . WPINC . '/ID3/class-getid3.php' );
     2476        $id3 = new getID3();
     2477        $data = $id3->analyze( $file );
     2478
     2479        if ( isset( $data['video']['lossless'] ) )
     2480                $metadata['lossless'] = $data['video']['lossless'];
     2481        if ( ! empty( $data['video']['bitrate'] ) )
     2482                $metadata['bitrate'] = (int) $data['video']['bitrate'];
     2483        if ( ! empty( $data['video']['bitrate_mode'] ) )
     2484                $metadata['bitrate_mode'] = $data['video']['bitrate_mode'];
     2485        if ( ! empty( $data['filesize'] ) )
     2486                $metadata['filesize'] = (int) $data['filesize'];
     2487        if ( ! empty( $data['mime_type'] ) )
     2488                $metadata['mime_type'] = $data['mime_type'];
     2489        if ( ! empty( $data['playtime_seconds'] ) )
     2490                $metadata['length'] = (int) ceil( $data['playtime_seconds'] );
     2491        if ( ! empty( $data['playtime_string'] ) )
     2492                $metadata['length_formatted'] = $data['playtime_string'];
     2493        if ( ! empty( $data['video']['resolution_x'] ) )
     2494                $metadata['width'] = (int) $data['video']['resolution_x'];
     2495        if ( ! empty( $data['video']['resolution_y'] ) )
     2496                $metadata['height'] = (int) $data['video']['resolution_y'];
     2497        if ( ! empty( $data['fileformat'] ) )
     2498                $metadata['fileformat'] = $data['fileformat'];
     2499        if ( ! empty( $data['video']['dataformat'] ) )
     2500                $metadata['dataformat'] = $data['video']['dataformat'];
     2501        if ( ! empty( $data['video']['encoder'] ) )
     2502                $metadata['encoder'] = $data['video']['encoder'];
     2503        if ( ! empty( $data['video']['codec'] ) )
     2504                $metadata['codec'] = $data['video']['codec'];
     2505
     2506        unset( $data['audio']['streams'] );
     2507        $metadata['audio'] = $data['audio'];
     2508
     2509        wp_add_id3_tag_data( $metadata, $data );
     2510
     2511        return $metadata;
     2512}
     2513
     2514/**
     2515 * Retrieve metadata from a audio file's ID3 tags
     2516 *
     2517 * @since 3.6.0
     2518 *
     2519 * @param string $file Path to file.
     2520 * @return array|boolean Returns array of metadata, if found.
     2521 */
     2522function wp_read_audio_metadata( $file ) {
     2523        if ( ! file_exists( $file ) )
     2524                return false;
     2525        $metadata = array();
     2526
     2527        if ( ! class_exists( 'getID3' ) )
     2528                require( ABSPATH . WPINC . '/ID3/class-getid3.php' );
     2529        $id3 = new getID3();
     2530        $data = $id3->analyze( $file );
     2531
     2532        if ( ! empty( $data['audio'] ) ) {
     2533                unset( $data['audio']['streams'] );
     2534                $metadata = $data['audio'];
     2535        }
     2536
     2537        if ( ! empty( $data['fileformat'] ) )
     2538                $metadata['fileformat'] = $data['fileformat'];
     2539        if ( ! empty( $data['filesize'] ) )
     2540                $metadata['filesize'] = (int) $data['filesize'];
     2541        if ( ! empty( $data['mime_type'] ) )
     2542                $metadata['mime_type'] = $data['mime_type'];
     2543        if ( ! empty( $data['playtime_seconds'] ) )
     2544                $metadata['length'] = (int) ceil( $data['playtime_seconds'] );
     2545        if ( ! empty( $data['playtime_string'] ) )
     2546                $metadata['length_formatted'] = $data['playtime_string'];
     2547
     2548        wp_add_id3_tag_data( $metadata, $data );
     2549
     2550        return $metadata;
     2551}
  • wp-admin/includes/post.php

    diff --git wp-admin/includes/post.php wp-admin/includes/post.php
    index dfd47b0..b20ff6d 100644
    function wp_edit_posts_query( $q = false ) { 
    868868        $posts_per_page = apply_filters( $per_page, $posts_per_page );
    869869        $posts_per_page = apply_filters( 'edit_posts_per_page', $posts_per_page, $post_type );
    870870
    871         $query = compact('post_type', 'post_status', 'perm', 'order', 'orderby', 'posts_per_page');
     871        $query = compact( 'post_type', 'post_status', 'perm', 'order', 'orderby', 'posts_per_page' );
     872        if ( ! empty( $q['format'] ) ) {
     873                $query['taxonomy'] = 'post_format';
     874                $term = get_term( $q['format'], $query['taxonomy'] );
     875                $query['term'] = $term->slug;
     876        }
    872877
    873878        // Hierarchical types require special args.
    874879        if ( is_post_type_hierarchical( $post_type ) && !isset($orderby) ) {
  • wp-admin/js/post-formats.js

    diff --git wp-admin/js/post-formats.js wp-admin/js/post-formats.js
    index 27f638a..3dbda7b 100644
    window.wp = window.wp || {}; 
    1212                $this.addClass('nav-tab-active').blur();
    1313                $('#post_format').val(format);
    1414                $('#post-body-content').attr('class', 'wp-format-' + format );
     15
     16                var ed = tinymce.get( 'content' ), edBody, format;
     17                if ( ed && this.id ) {
     18                        edBody = ed.getBody();
     19                        format = 'post-format-' + this.id; // also need to handle 'post-format-0'
     20                        edBody.className = edBody.className.replace( /\bpost-format-[^ ]+/, '' );
     21                        ed.dom.addClass( edBody, format );
     22                }
    1523        });
    1624
    1725        // Image selection
  • wp-includes/class-wp-editor.php

    diff --git wp-includes/class-wp-editor.php wp-includes/class-wp-editor.php
    index 38ab7c2..4622db8 100644
    final class _WP_Editors { 
    395395                        }
    396396
    397397                        $body_class = $editor_id;
    398 
    399                         if ( $post = get_post() )
    400                                 $body_class .= ' post-type-' . $post->post_type;
     398                        $post = get_post();
     399
     400                        if ( $post ) {
     401                                $body_class .= ' post-type-' . $post->post_type . ' post-status-' . $post->post_status;
     402                                if ( post_type_supports( $post->post_type, 'post-formats' ) ) {
     403                                        $post_format = get_post_format( $post );
     404                                        if ( $post_format && ! is_wp_error( $post_format ) )
     405                                                $body_class .= ' post-format-' . sanitize_html_class( $post_format );
     406                                        else
     407                                                $body_class .= ' post-format-standard';
     408                                }
     409                        }
    401410
    402411                        if ( !empty($set['tinymce']['body_class']) ) {
    403412                                $body_class .= ' ' . $set['tinymce']['body_class'];
  • wp-includes/functions.php

    diff --git wp-includes/functions.php wp-includes/functions.php
    index e0b8cb8..ca414ea 100644
    $("#wp-auth-check-form iframe").load(function(){ 
    40204020</script>
    40214021</div>' ) );
    40224022}
     4023
     4024/**
     4025 * Return RegEx body to liberally match an opening HTML tag that:
     4026 * 1. Is self-closing or
     4027 * 2. Has no body but has a closing tag of the same name or
     4028 * 3. Contains a body and a closing tag of the same name
     4029 *
     4030 * Note: this RegEx does not balance inner tags and does not attempt to produce valid HTML
     4031 *
     4032 * @since 3.6.0
     4033 *
     4034 * @param string $tag An HTML tag name. Example: 'video'
     4035 * @return string
     4036 */
     4037function get_tag_regex( $tag ) {
     4038        if ( empty( $tag ) )
     4039                return;
     4040
     4041        return sprintf( '(<%1$s[^>]*(?:/?>$|>[\s\S]*?</%1$s>))', tag_escape( $tag ) );
     4042}
     4043 No newline at end of file
  • wp-includes/js/media-editor.js

    diff --git wp-includes/js/media-editor.js wp-includes/js/media-editor.js
    index 15eff8d..7dbbb79 100644
     
    6666                                        src:       size.url,
    6767                                        captionId: 'attachment_' + attachment.id
    6868                                });
    69 
     69                        } else if ( 'video' === attachment.type || 'audio' === attachment.type ) {
     70                                _.extend( props, _.pick( attachment, 'title', 'type', 'icon', 'mime' ) );
    7071                        // Format properties for non-images.
    7172                        } else {
    7273                                props.title = props.title || attachment.filename;
     
    9596                        return wp.html.string( options );
    9697                },
    9798
     99                audio: function( props, attachment ) {
     100                        var shortcode, html;
     101
     102                        props = wp.media.string.props( props, attachment );
     103
     104                        shortcode = {};
     105
     106                        if ( props.mime ) {
     107                                switch ( props.mime ) {
     108                                case 'audio/mpeg':
     109                                        if ( props.linkUrl.indexOf( 'mp3' ) )
     110                                                shortcode.mp3 = props.linkUrl;
     111                                        else if ( props.linkUrl.indexOf( 'm4a' ) )
     112                                                shortcode.m4a = props.linkUrl;
     113                                        break;
     114                                case 'audio/mp3':
     115                                        shortcode.mp3 = props.linkUrl;
     116                                        break;
     117                                case 'audio/m4a':
     118                                        shortcode.m4a = props.linkUrl;
     119                                        break;
     120                                case 'audio/wav':
     121                                        shortcode.wav = props.linkUrl;
     122                                        break;
     123                                case 'audio/ogg':
     124                                        shortcode.ogg = props.linkUrl;
     125                                        break;
     126                                case 'audio/x-ms-wma':
     127                                case 'audio/wma':
     128                                        shortcode.wma = props.linkUrl;
     129                                        break;
     130                                }
     131                        }
     132
     133                        html = wp.shortcode.string({
     134                                tag:     'audio',
     135                                attrs:   shortcode
     136                        });
     137
     138                        return html;
     139                },
     140
     141                video: function( props, attachment ) {
     142                        var shortcode, html;
     143
     144                        props = wp.media.string.props( props, attachment );
     145
     146                        shortcode = {};
     147
     148                        if ( props.mime ) {
     149                                switch ( props.mime ) {
     150                                case 'video/mp4':
     151                                        shortcode.mp4 = props.linkUrl;
     152                                        break;
     153                                case 'video/m4v':
     154                                        shortcode.m4v = props.linkUrl;
     155                                        break;
     156                                case 'video/webm':
     157                                        shortcode.webm = props.linkUrl;
     158                                        break;
     159                                case 'video/ogg':
     160                                        shortcode.ogv = props.linkUrl;
     161                                        break;
     162                                case 'video/x-ms-wmv':
     163                                case 'video/wmv':
     164                                case 'video/asf':
     165                                        shortcode.wmv = props.linkUrl;
     166                                        break;
     167                                case 'video/flv':
     168                                case 'video/x-flv':
     169                                        shortcode.flv = props.linkUrl;
     170                                        break;
     171                                }
     172                        }
     173
     174                        html = wp.shortcode.string({
     175                                tag:     'video',
     176                                attrs:   shortcode
     177                        });
     178
     179                        return html;
     180                },
     181
    98182                image: function( props, attachment ) {
    99183                        var img = {},
    100184                                options, classes, shortcode, html;
     
    575659                                                if ( props[ prop ] )
    576660                                                        options[ option ] = props[ prop ];
    577661                                        });
    578 
     662                                } else if ( 'video' === attachment.type ) {
     663                                        html = wp.media.string.video( props );
     664                                } else if ( 'audio' === attachment.type ) {
     665                                        html = wp.media.string.audio( props );
    579666                                } else {
    580667                                        html = wp.media.string.link( props );
    581668                                        options.post_title = props.title;
  • wp-includes/media.php

    diff --git wp-includes/media.php wp-includes/media.php
    index 9ef641c..bffba5e 100644
    function gallery_shortcode($attr) { 
    805805}
    806806
    807807/**
     808 * Provide a No-JS Flash fallback as a last resort for audio / video
     809 *
     810 * @since 3.6.0
     811 *
     812 * @param string $url
     813 * @return string Fallback HTML
     814 */
     815function wp_mediaelement_fallback( $url ) {
     816        return apply_filters( 'wp_mediaelement_fallback', sprintf( '<a href="%1$s">%1$s</a>', esc_url( $url ) ), $url );
     817}
     818
     819/**
     820 * Return a filtered list of WP-supported audio formats
     821 *
     822 * @since 3.6.0
     823 * @return array
     824 */
     825function wp_get_audio_extensions() {
     826        return apply_filters( 'wp_audio_extensions', array( 'mp3', 'ogg', 'wma', 'm4a', 'wav' ) );
     827}
     828
     829/**
     830 * The Audio shortcode.
     831 *
     832 * This implements the functionality of the Audio Shortcode for displaying
     833 * WordPress mp3s in a post.
     834 *
     835 * @since 3.6.0
     836 *
     837 * @param array $attr Attributes of the shortcode.
     838 * @return string HTML content to display audio.
     839 */
     840function wp_audio_shortcode( $attr ) {
     841        $post_id = get_post() ? get_the_ID() : 0;
     842
     843        static $instances = 0;
     844        $instances++;
     845
     846        $audio = null;
     847
     848        $default_types = wp_get_audio_extensions();
     849        $defaults_atts = array( 'src' => '' );
     850        foreach ( $default_types as $type  )
     851                $defaults_atts[$type] = '';
     852
     853        $atts = shortcode_atts( $defaults_atts, $attr );
     854        extract( $atts );
     855
     856        $primary = false;
     857        if ( ! empty( $src ) ) {
     858                $type = wp_check_filetype( $src );
     859                if ( ! in_array( $type['ext'], $default_types ) ) {
     860                        printf( '<a class="wp-post-format-link-audio" href="%1$s">%1$s</a>', $src );
     861                        return;
     862                }
     863                $primary = true;
     864                array_unshift( $default_types, 'src' );
     865        } else {
     866                foreach ( $default_types as $ext ) {
     867                        if ( ! empty( $$ext ) ) {
     868                                $type = wp_check_filetype( $$ext );
     869                                if ( $type['ext'] === $ext )
     870                                        $primary = true;
     871                        }
     872                }
     873        }
     874
     875        if ( ! $primary ) {
     876                $audios = get_post_audio( $post_id );
     877                if ( empty( $audios ) )
     878                        return;
     879
     880                $audio = reset( $audios );
     881                $src = wp_get_attachment_url( $audio->ID );
     882                if ( empty( $src ) )
     883                        return;
     884
     885                array_unshift( $default_types, 'src' );
     886        }
     887
     888        $library = apply_filters( 'wp_audio_shortcode_library', 'mediaelement' );
     889        if ( 'mediaelement' === $library ) {
     890                wp_enqueue_style( 'wp-mediaelement' );
     891                wp_enqueue_script( 'wp-mediaelement' );
     892        }
     893
     894        $atts = array(
     895                sprintf( 'class="%s"', apply_filters( 'wp_audio_shortcode_class', 'wp-audio-shortcode' ) ),
     896                sprintf( 'id="audio-%d-%d"', $post_id, $instances ),
     897        );
     898
     899        $html = sprintf( '<audio %s controls="controls" preload="none">', join( ' ', $atts ) );
     900
     901        $fileurl = '';
     902        $source = '<source type="%s" src="%s" />';
     903        foreach ( $default_types as $fallback ) {
     904                if ( ! empty( $$fallback ) ) {
     905                        if ( empty( $fileurl ) )
     906                                $fileurl = $$fallback;
     907                        $type = wp_check_filetype( $$fallback );
     908                        $html .= sprintf( $source, $type['type'], $$fallback );
     909                }
     910        }
     911
     912        if ( 'mediaelement' === $library )
     913                $html .= wp_mediaelement_fallback( $fileurl );
     914        $html .= '</audio>';
     915
     916        return apply_filters( 'wp_audio_shortcode', $html, $atts, $audio, $post_id );
     917}
     918add_shortcode( 'audio', apply_filters( 'wp_audio_shortcode_handler', 'wp_audio_shortcode' ) );
     919
     920/**
     921 * Return a filtered list of WP-supported video formats
     922 *
     923 * @since 3.6.0
     924 * @return array
     925 */
     926function wp_get_video_extensions() {
     927        return apply_filters( 'wp_video_extensions', array( 'mp4', 'm4v', 'webm', 'ogv', 'wmv', 'flv' ) );
     928}
     929
     930/**
     931 * The Video shortcode.
     932 *
     933 * This implements the functionality of the Video Shortcode for displaying
     934 * WordPress mp4s in a post.
     935 *
     936 * @since 3.6.0
     937 *
     938 * @param array $attr Attributes of the shortcode.
     939 * @return string HTML content to display video.
     940 */
     941function wp_video_shortcode( $attr ) {
     942        global $content_width;
     943        $post_id = get_post() ? get_the_ID() : 0;
     944
     945        static $instances = 0;
     946        $instances++;
     947
     948        $video = null;
     949
     950        $default_types = wp_get_video_extensions();
     951        $defaults_atts = array(
     952                'src' => '',
     953                'poster' => '',
     954                'height' => 360,
     955                'width' => empty( $content_width ) ? 640 : $content_width,
     956        );
     957        foreach ( $default_types as $type  )
     958                $defaults_atts[$type] = '';
     959
     960        $atts = shortcode_atts( $defaults_atts, $attr );
     961        extract( $atts );
     962
     963        $primary = false;
     964        if ( ! empty( $src ) ) {
     965                $type = wp_check_filetype( $src );
     966                if ( ! in_array( $type['ext'], $default_types ) ) {
     967                        printf( '<a class="wp-post-format-link-video" href="%1$s">%1$s</a>', $src );
     968                        return;
     969                }
     970                $primary = true;
     971                array_unshift( $default_types, 'src' );
     972        } else {
     973                foreach ( $default_types as $ext ) {
     974                        if ( ! empty( $$ext ) ) {
     975                                $type = wp_check_filetype( $$ext );
     976                                if ( $type['ext'] === $ext )
     977                                        $primary = true;
     978                        }
     979                }
     980        }
     981
     982        if ( ! $primary ) {
     983                $videos = get_post_video( $post_id );
     984                if ( empty( $videos ) )
     985                        return;
     986
     987                $video = reset( $videos );
     988                $src = wp_get_attachment_url( $video->ID );
     989                if ( empty( $src ) )
     990                        return;
     991
     992                array_unshift( $default_types, 'src' );
     993        }
     994
     995        $library = apply_filters( 'wp_video_shortcode_library', 'mediaelement' );
     996        if ( 'mediaelement' === $library ) {
     997                wp_enqueue_style( 'wp-mediaelement' );
     998                wp_enqueue_script( 'wp-mediaelement' );
     999        }
     1000
     1001        $atts = array(
     1002                sprintf( 'class="%s"', apply_filters( 'wp_video_shortcode_class', 'wp-video-shortcode' ) ),
     1003                sprintf( 'id="video-%d-%d"', $post_id, $instances ),
     1004                sprintf( 'width="%d"', $width ),
     1005                sprintf( 'height="%d"', $height ),
     1006        );
     1007
     1008        if ( ! empty( $poster ) )
     1009                $atts[] = sprintf( 'poster="%s"', esc_url( $poster ) );
     1010
     1011        $html = sprintf( '<video %s controls="controls" preload="none">', join( ' ', $atts ) );
     1012
     1013        $fileurl = '';
     1014        $source = '<source type="%s" src="%s" />';
     1015        foreach ( $default_types as $fallback ) {
     1016                if ( ! empty( $$fallback ) ) {
     1017                        if ( empty( $fileurl ) )
     1018                                $fileurl = $$fallback;
     1019                        $type = wp_check_filetype( $$fallback );
     1020                        // m4v sometimes shows up as video/mpeg which collides with mp4
     1021                        if ( 'm4v' === $type['ext'] )
     1022                                $type['type'] = 'video/m4v';
     1023                        $html .= sprintf( $source, $type['type'], $$fallback );
     1024                }
     1025        }
     1026        if ( 'mediaelement' === $library )
     1027                $html .= wp_mediaelement_fallback( $fileurl, $width, $height );
     1028        $html .= '</video>';
     1029
     1030        return apply_filters( 'wp_video_shortcode', $html, $atts, $video, $post_id );
     1031}
     1032add_shortcode( 'video', apply_filters( 'wp_video_shortcode_handler', 'wp_video_shortcode' ) );
     1033
     1034/**
    8081035 * Display previous image link that has the same post parent.
    8091036 *
    8101037 * @since 2.5.0
    function wp_enqueue_media( $args = array() ) { 
    15441771
    15451772        do_action( 'wp_enqueue_media' );
    15461773}
     1774
     1775/**
     1776 * Retrieve images attached to the passed post
     1777 *
     1778 * @since 3.6.0
     1779 *
     1780 * @param int $post_id  Post ID
     1781 * @return array Found image attachments
     1782 */
     1783function get_attached_images( $post_id = 0 ) {
     1784        $post = empty( $post_id ) ? get_post() : get_post( $post_id );
     1785        if ( empty( $post ) )
     1786                return array();
     1787
     1788        $children = get_children( array(
     1789                'post_parent' => $post->ID,
     1790                'post_type' => 'attachment',
     1791                'post_mime_type' => 'image',
     1792                'posts_per_page' => -1,
     1793                'orderby' => 'menu_order',
     1794                'order' => 'ASC'
     1795        ) );
     1796
     1797        if ( ! empty( $children ) )
     1798                return $children;
     1799
     1800        return array();
     1801}
     1802
     1803/**
     1804 * Retrieve images attached to the passed post
     1805 *
     1806 * @since 3.6.0
     1807 *
     1808 * @param int $post_id  Post ID
     1809 * @return array Found image attachments
     1810 */
     1811function get_attached_image_srcs( $post_id = 0 ) {
     1812        $children = get_attached_images( $post_id );
     1813        if ( empty( $children ) )
     1814                return array();
     1815
     1816        $srcs = array();
     1817        foreach ( $children as $attachment )
     1818                $srcs[] = wp_get_attachment_url( $attachment->ID );
     1819
     1820        return $srcs;
     1821}
     1822
     1823/**
     1824 * Check the content blob for images
     1825 *
     1826 * @since 3.6.0
     1827 *
     1828 * @param string $content A string which might contain image data.
     1829 * @param boolean $remove Whether to remove the found data from the passed content.
     1830 * @param int $limit Optional. The number of galleries to return
     1831 * @return string The found data
     1832 */
     1833function get_content_images( &$content, $remove = false, $limit = 0 ) {
     1834        $src = '';
     1835        $srcs = array();
     1836        $matches = array();
     1837
     1838        if ( preg_match_all( '#' . get_tag_regex( 'img' ) . '#i', $content, $matches, PREG_SET_ORDER ) && ! empty( $matches ) ) {
     1839                foreach ( $matches as $tag ) {
     1840                        $count = 1;
     1841                        if ( $remove )
     1842                                $content = str_replace( $tag[0], '', $content, $count );
     1843
     1844                        preg_match( '#src=[\'"](.+?)[\'"]#is', $tag[1], $src );
     1845                        if ( ! empty( $src[1] ) ) {
     1846                                $srcs[] = $src[1];
     1847                                if ( $limit > 0 && count( $srcs ) >= $limit )
     1848                                        break;
     1849                        }
     1850                }
     1851        }
     1852
     1853        return array_values( array_unique( $srcs ) );
     1854}
     1855
     1856/**
     1857 * Check the content blob for images and return the first
     1858 *
     1859 * @since 3.6.0
     1860 *
     1861 * @param string $content A string which might contain image data.
     1862 * @param boolean $remove Whether to remove the found data from the passed content.
     1863 * @return string The found data
     1864 */
     1865function get_content_image( &$content, $remove = false ) {
     1866        $srcs = get_content_images( $content, $remove, 1 );
     1867        return reset( $srcs );
     1868}
     1869
     1870/**
     1871 * Check the content blob for galleries and return their image srcs
     1872 *
     1873 * @since 3.6.0
     1874 *
     1875 * @param string $content A string which might contain image data.
     1876 * @param boolean $remove Optional. Whether to remove the found data from the passed content.
     1877 * @param int $limit Optional. The number of galleries to return
     1878 * @return array A list of galleries, which in turn are a list of their srcs in order
     1879 */
     1880function get_content_galleries( &$content, $remove = false, $limit = 0 ) {
     1881        $src = '';
     1882        $galleries = array();
     1883        $matches = array();
     1884
     1885        if ( preg_match_all( '/' . get_shortcode_regex() . '/s', $content, $matches, PREG_SET_ORDER ) && ! empty( $matches ) ) {
     1886                foreach ( $matches as $shortcode ) {
     1887                        if ( 'gallery' === $shortcode[2] ) {
     1888                                $srcs = array();
     1889                                $data = array();
     1890                                $count = 1;
     1891                                if ( $remove )
     1892                                        $content = str_replace( $shortcode[0], '', $content, $count );
     1893
     1894                                $gallery = do_shortcode_tag( $shortcode );
     1895                                preg_match_all( '#src=[\'"](.+?)[\'"]#is', $gallery, $src, PREG_SET_ORDER );
     1896                                if ( ! empty( $src ) ) {
     1897                                        foreach ( $src as $s )
     1898                                                $srcs[] = $s[1];
     1899                                }
     1900                                // the function will eventually return more data about the gallery
     1901                                $data['src'] = array_values( array_unique( $srcs ) );
     1902                                $galleries[] = $data;
     1903                                if ( $limit > 0 && count( $galleries ) >= $limit )
     1904                                        break;
     1905                        }
     1906                }
     1907        }
     1908
     1909        return $galleries;
     1910}
     1911
     1912/**
     1913 * Retrieve galleries from the passed post's content
     1914 *
     1915 * @since 3.6.0
     1916 *
     1917 * @param int $post_id A string which might contain image data.
     1918 * @return array A list of galleries, which in turn are a list of their srcs in order
     1919 */
     1920function get_post_galleries_images( $post_id = 0 ) {
     1921        $post = empty( $post_id ) ? clone get_post() : get_post( $post_id );
     1922        if ( empty( $post ) )
     1923                return array();
     1924
     1925        $data = get_content_galleries( $post->post_content );
     1926        return wp_list_pluck( $data, 'src' );
     1927}
     1928
     1929/**
     1930 * Check the content blob for galleries and return the image srcs for the first found gallery
     1931 *
     1932 * @since 3.6.0
     1933 *
     1934 * @param int $post_id A string which might contain image data.
     1935 * @return array A list of a gallery's image srcs in order
     1936 */
     1937function get_post_gallery_images( $post_id = 0 ) {
     1938        $post = empty( $post_id ) ? clone get_post() : get_post( $post_id );
     1939        if ( empty( $post ) )
     1940                return array();
     1941
     1942        $data = get_content_galleries( $post->post_content, false, 1 );
     1943        return reset( wp_list_pluck( $data, 'src' ) );
     1944}
     1945
     1946
     1947/**
     1948 * Retrieve video attached to the passed post
     1949 *
     1950 * @since 3.6.0
     1951 *
     1952 * @return array Found video attachments
     1953 */
     1954function get_post_video( $post_id = 0 ) {
     1955        $post = empty( $post_id ) ? get_post() : get_post( $post_id );
     1956        if ( empty( $post ) )
     1957                return;
     1958
     1959        $children = get_children( array(
     1960                'post_parent' => $post->ID,
     1961                'post_type' => 'attachment',
     1962                'post_mime_type' => 'video',
     1963                'posts_per_page' => -1
     1964        ) );
     1965
     1966        if ( ! empty( $children ) )
     1967                return $children;
     1968}
     1969/**
     1970 * Retrieve audio attached to the passed post
     1971 *
     1972 * @since 3.6.0
     1973 *
     1974 * @param int $post_id  Post ID
     1975 * @return array Found audio attachments
     1976 */
     1977function get_post_audio( $post_id = 0 ) {
     1978        $post = empty( $post_id ) ? get_post() : get_post( $post_id );
     1979        if ( empty( $post ) )
     1980                return;
     1981
     1982        $children = get_children( array(
     1983                'post_parent' => $post->ID,
     1984                'post_type' => 'attachment',
     1985                'post_mime_type' => 'audio',
     1986                'posts_per_page' => -1
     1987        ) );
     1988
     1989        if ( ! empty( $children ) )
     1990                return $children;
     1991
     1992        return array();
     1993}
     1994
     1995/**
     1996 * Extract the srcs from the post's [audio] <source>s
     1997 *
     1998 * @since 3.6.0
     1999 *
     2000 * @param string $content A string which might contain audio data.
     2001 * @param boolean $remove Whether to remove the found URL from the passed content.
     2002 * @return array A list of lists. Each item has a list of sources corresponding
     2003 *              to a [audio]'s primary src and specified fallbacks
     2004 */
     2005function get_content_audio( &$content, $remove = false ) {
     2006        $src = '';
     2007        $audios = array();
     2008        $matches = array();
     2009
     2010        if ( preg_match_all( '/' . get_shortcode_regex() . '/s', $content, $matches, PREG_SET_ORDER ) && ! empty( $matches ) ) {
     2011                foreach ( $matches as $shortcode ) {
     2012                        if ( 'audio' === $shortcode[2] ) {
     2013                                $srcs = array();
     2014                                $count = 1;
     2015                                if ( $remove )
     2016                                        $content = str_replace( $shortcode[0], '', $content, $count );
     2017
     2018                                $audio = do_shortcode_tag( $shortcode );
     2019                                preg_match_all( '#src=[\'"](.+?)[\'"]#is', $audio, $src, PREG_SET_ORDER );
     2020                                if ( ! empty( $src ) ) {
     2021                                        foreach ( $src as $s )
     2022                                                $srcs[] = $s[1];
     2023
     2024                                        $audios[] = array_values( array_unique( $srcs ) );
     2025                                }
     2026                        }
     2027                }
     2028        }
     2029        return $audios;
     2030}
     2031
     2032/**
     2033 * Check the content blob for an <audio>, <object>, <embed>, or <iframe>, in that order
     2034 * If no HTML tag is found, check the first line of the post for a URL
     2035 *
     2036 * @since 3.6.0
     2037 *
     2038 * @param string $content A string which might contain audio data.
     2039 * @param boolean $remove Whether to remove the found URL from the passed content.
     2040 * @return array A list of found HTML audio embeds and possibly a URL by itself
     2041 */
     2042function get_embedded_audio( &$content, $remove = false ) {
     2043        $html = array();
     2044        $matches = '';
     2045
     2046        foreach ( array( 'audio', 'object', 'embed', 'iframe' ) as $tag ) {
     2047                if ( preg_match( '#' . get_tag_regex( $tag ) . '#', $content, $matches ) ) {
     2048                        $html[] = $matches[1];
     2049                        if ( $remove )
     2050                                $content = str_replace( $matches[0], '', $content );
     2051
     2052                        return $html;
     2053                }
     2054        }
     2055
     2056        $lines = explode( "\n", trim( $content ) );
     2057        $line = trim( array_shift( $lines  ) );
     2058
     2059        if ( 0 === stripos( $line, 'http' ) ) {
     2060                if ( $remove )
     2061                        $content = join( "\n", $lines );
     2062
     2063                $html[] = $line;
     2064        }
     2065        return $html;
     2066}
     2067
     2068/**
     2069 * Extract the srcs from the post's [video] <source>s
     2070 *
     2071 * @since 3.6.0
     2072 *
     2073 * @param string $content A string which might contain video data.
     2074 * @param boolean $remove Whether to remove the found URL from the passed content.
     2075 * @return array A list of lists. Each item has a list of sources corresponding
     2076 *              to a [video]'s primary src and specified fallbacks
     2077 */
     2078function get_content_video( &$content, $remove = false ) {
     2079        $src = '';
     2080        $videos = array();
     2081        $matches = array();
     2082
     2083        if ( preg_match_all( '/' . get_shortcode_regex() . '/s', $content, $matches, PREG_SET_ORDER ) && ! empty( $matches ) ) {
     2084                foreach ( $matches as $shortcode ) {
     2085                        if ( 'video' === $shortcode[2] ) {
     2086                                $srcs = array();
     2087                                $count = 1;
     2088                                if ( $remove )
     2089                                        $content = str_replace( $shortcode[0], '', $content, $count );
     2090
     2091                                $video = do_shortcode_tag( $shortcode );
     2092                                preg_match_all( '#src=[\'"](.+?)[\'"]#is', $video, $src, PREG_SET_ORDER );
     2093                                if ( ! empty( $src ) ) {
     2094                                        foreach ( $src as $s )
     2095                                                $srcs[] = $s[1];
     2096
     2097                                        $videos[] = array_values( array_unique( $srcs ) );
     2098                                }
     2099                        }
     2100                }
     2101        }
     2102        return $videos;
     2103}
     2104
     2105/**
     2106 * Check the content blob for a <video>, <object>, <embed>, or <iframe>, in that order
     2107 * If no HTML tag is found, check the first line of the post for a URL
     2108 *
     2109 * @since 3.6.0
     2110 *
     2111 * @param string $content A string which might contain video data.
     2112 * @param boolean $remove Whether to remove the found URL from the passed content.
     2113 * @return array A list of found HTML video embeds and possibly a URL by itself
     2114 */
     2115function get_embedded_video( &$content, $remove = false ) {
     2116        $html = array();
     2117        $matches = '';
     2118        foreach ( array( 'video', 'object', 'embed', 'iframe' ) as $tag ) {
     2119                if ( preg_match( '#' . get_tag_regex( $tag ) . '#', $content, $matches ) ) {
     2120                        $html[] = $matches[1];
     2121                        if ( $remove )
     2122                                $content = str_replace( $matches[0], '', $content );
     2123                }
     2124        }
     2125
     2126        $lines = explode( "\n", trim( $content ) );
     2127        $line = trim( array_shift( $lines  ) );
     2128
     2129        if ( 0 === stripos( $line, 'http' ) ) {
     2130                if ( $remove )
     2131                        $content = join( "\n", $lines );
     2132
     2133                $html[] = $line;
     2134        }
     2135        return $html;
     2136}
     2137
     2138/**
     2139 * Audio embed handler callback.
     2140 *
     2141 * @since 3.6.0
     2142 *
     2143 * @param array $matches The regex matches from the provided regex when calling {@link wp_embed_register_handler()}.
     2144 * @param array $attr Embed attributes.
     2145 * @param string $url The original URL that was matched by the regex.
     2146 * @param array $rawattr The original unmodified attributes.
     2147 * @return string The embed HTML.
     2148 */
     2149function wp_audio_embed( $matches, $attr, $url, $rawattr ) {
     2150        $audio = $url;
     2151        if ( shortcode_exists( 'audio' ) )
     2152                $audio = do_shortcode( '[audio src="' . $url . '" /]' );
     2153        return apply_filters( 'wp_audio_embed', $audio, $attr, $url, $rawattr );
     2154}
     2155wp_embed_register_handler( 'wp_audio_embed', '#https?://.+?\.(' . join( '|', wp_get_audio_extensions() ) . ')#i', apply_filters( 'wp_audio_embed_handler', 'wp_audio_embed' ), 9999 );
     2156
     2157/**
     2158 * Video embed handler callback.
     2159 *
     2160 * @since 3.6.0
     2161 *
     2162 * @param array $matches The regex matches from the provided regex when calling {@link wp_embed_register_handler()}.
     2163 * @param array $attr Embed attributes.
     2164 * @param string $url The original URL that was matched by the regex.
     2165 * @param array $rawattr The original unmodified attributes.
     2166 * @return string The embed HTML.
     2167 */
     2168function wp_video_embed( $matches, $attr, $url, $rawattr ) {
     2169        $dimensions = '';
     2170        $video = $url;
     2171        if ( shortcode_exists( 'video' ) ) {
     2172                if ( ! empty( $rawattr['width'] ) && ! empty( $rawattr['height'] ) ) {
     2173                        $dimensions .= sprintf( 'width="%d" ', (int) $rawattr['width'] );
     2174                        $dimensions .= sprintf( 'height="%d" ', (int) $rawattr['height'] );
     2175                }
     2176                $video = do_shortcode( '[video ' . $dimensions . 'src="' . $url . '" /]' );
     2177        }
     2178        return apply_filters( 'wp_video_embed', $video, $attr, $url, $rawattr );
     2179}
     2180wp_embed_register_handler( 'wp_video_embed', '#https?://.+?\.(' . join( '|', wp_get_video_extensions() ) . ')#i', apply_filters( 'wp_video_embed_handler', 'wp_video_embed' ), 9999 );
  • wp-includes/post-formats.php

    diff --git wp-includes/post-formats.php wp-includes/post-formats.php
    index 3896d11..9dd11ec 100644
    function post_formats_compat( $content, $id = 0 ) { 
    308308        $show_content = true;
    309309        $format_output = '';
    310310        $meta = get_post_format_meta( $post->ID );
     311        // passed by ref in preg_match()
     312        $matches = array();
    311313
    312314        switch ( $format ) {
    313315                case 'link':
    314316                        $compat['tag'] = '';
     317                        $compat['position'] = 'before';
    315318
    316319                        if ( ! empty( $meta['url'] ) ) {
    317320                                $esc_url = preg_quote( $meta['url'], '#' );
    318321                                // Make sure the same URL isn't in the post (modified/extended versions allowed)
    319                                 if ( ! preg_match( '#' . $esc_url . '[^/&\?]#', $content ) ) {
    320                                         $format_output .= sprintf(
    321                                                 '<a %shref="%s">%s</a>',
    322                                                 empty( $compat['link_class'] ) ? '' : sprintf( 'class="%s" ', esc_attr( $compat['link_class'] ) ),
    323                                                 esc_url( $meta['url'] ),
    324                                                 empty( $post->post_title ) ? esc_url( $meta['url'] ) : apply_filters( 'the_title', $post->post_title, $post->ID )
    325                                         );
     322                                if ( ! preg_match( '#' . $esc_url . '[^/&\?]?#', $content ) ) {
     323                                        $url = $meta['url'];
     324                                } else {
     325                                        $url = get_content_link( $content, true );
    326326                                }
     327                        } else {
     328                                $content_before = $content;
     329                                $url = get_content_link( $content, true );
     330                                if ( $content_before == $content )
     331                                        $url = '';
    327332                        }
     333
     334                        if ( ! empty( $url ) ) {
     335                                $format_output .= sprintf(
     336                                        '<a %shref="%s">%s</a>',
     337                                        empty( $compat['link_class'] ) ? '' : sprintf( 'class="%s" ', esc_attr( $compat['link_class'] ) ),
     338                                        esc_url( $url ),
     339                                        empty( $post->post_title ) ? esc_url( $meta['url'] ) : apply_filters( 'the_title', $post->post_title )
     340                                );
     341                        }
    328342                        break;
    329343
    330344                case 'quote':
    function post_formats_compat( $content, $id = 0 ) { 
    365379                        break;
    366380
    367381                case 'gallery':
    368                         preg_match_all( '/' . get_shortcode_regex() . '/s', $content, $matches );
    369                         if ( ! empty( $matches ) && isset( $matches[2] ) ) {
    370                                 foreach ( (array) $matches[2] as $match ) {
    371                                         if ( 'gallery' === $match )
    372                                                 break 2; // foreach + case
    373                                 }
    374                         }
    375 
    376                         if ( ! empty( $meta['gallery'] ) ) {
     382                        if ( ! has_shortcode( $post->post_content, $format ) && ! empty( $meta['gallery'] ) )
    377383                                $format_output .= $meta['gallery'];
    378                         }
    379384                        break;
    380385
    381386                case 'video':
    382387                case 'audio':
    383                         $shortcode_regex = '/' . get_shortcode_regex() . '/s';
    384                         $matches = preg_match( $shortcode_regex, $content );
    385                         if ( ! $matches || $format !== $matches[2] ) {
    386                                 if ( ! empty( $meta['media'] ) ) {
    387                                         // the metadata is a shortcode or an embed code
    388                                         if ( preg_match( $shortcode_regex, $meta['media'] ) || preg_match( '#<[^>]+>#', $meta['media'] ) ) {
    389                                                 $format_output .= $meta['media'];
    390                                         } elseif ( ! stristr( $content, $meta['media'] ) ) {
    391                                                 // attempt to embed the URL
    392                                                 $format_output .= sprintf( '[embed]%s[/embed]', $meta['media'] );
    393                                         }
     388                        if ( ! has_shortcode( $post->post_content, $format ) && ! empty( $meta['media'] ) ) {
     389                                // the metadata is a shortcode or an embed code
     390                                if ( preg_match( '/' . get_shortcode_regex() . '/s', $meta['media'] ) || preg_match( '#<[^>]+>#', $meta['media'] ) ) {
     391                                        $format_output .= $meta['media'];
     392                                } elseif ( ! stristr( $content, $meta['media'] ) ) {
     393                                        // attempt to embed the URL
     394                                        $format_output .= sprintf( '[embed]%s[/embed]', $meta['media'] );
    394395                                }
    395396                        }
    396397                        break;
    function post_formats_compat( $content, $id = 0 ) { 
    420421
    421422        return $output;
    422423}
     424
     425/**
     426 * Extract a URL from passed content, if possible
     427 * Checks for a URL on the first line of the content or the first encountered href attribute.
     428 *
     429 * @since 3.6.0
     430 *
     431 * @param string $content A string which might contain a URL.
     432 * @param boolean $remove Whether the remove the found URL from the passed content.
     433 * @return string The found URL.
     434 */
     435function get_content_link( &$content, $remove = false ) {
     436        if ( empty( $content ) )
     437                return '';
     438
     439        $matches = array();
     440
     441        // the content is a URL
     442        $trimmed = trim( $content );
     443        if ( 0 === stripos( $trimmed, 'http' ) && ! preg_match( '#\s#', $trimmed ) ) {
     444                if ( $remove )
     445                        $content = '';
     446
     447                return $trimmed;
     448        // the content is HTML so we grab the first href
     449        } elseif ( preg_match( '/<a\s[^>]*?href=[\'"](.+?)[\'"]/is', $content, $matches ) ) {
     450                return esc_url_raw( $matches[1] );
     451        }
     452
     453        $lines = explode( "\n", $trimmed );
     454        $line = trim( array_shift( $lines ) );
     455
     456        // the content is a URL followed by content
     457        if ( 0 === stripos( $line, 'http' ) ) {
     458                if ( $remove )
     459                        $content = trim( join( "\n", $lines ) );
     460
     461                return esc_url_raw( $line );
     462        }
     463
     464        return '';
     465}
     466
     467/**
     468 * Attempt to retrieve a URL from a post's content
     469 *
     470 * @since 3.6.0
     471 *
     472 * @param int $id Optional. Post ID.
     473 * @return string A URL, if found.
     474 */
     475function get_the_link( $id = 0 ) {
     476        $post = empty( $id ) ? get_post() : get_post( $id );
     477        if ( empty( $post ) )
     478                return '';
     479
     480        if ( has_post_format( 'link', $post ) ) {
     481                $meta = get_post_format_meta( $post->ID );
     482                if ( ! empty( $meta['url'] ) )
     483                        return esc_url_raw( $meta['url'] );
     484        }
     485
     486        if ( ! empty( $post->post_content ) )
     487                return get_content_link( $post->post_content );
     488}
     489
     490/**
     491 * Attempt to output a URL from a post's content
     492 *
     493 * @since 3.6.0
     494 *.
     495 */
     496function the_link() {
     497        echo get_the_link();
     498}
     499
     500/**
     501 * Deliberately interpret passed content as a chat transcript that is optionally
     502 * followed by commentary
     503 *
     504 * If the content does not contain username syntax, assume that it does not contain
     505 * chat logs and return
     506 *
     507 * @since 3.6.0
     508 *
     509 * Example:
     510 *
     511 * One stanza of chat:
     512 * Scott: Hey, let's chat!
     513 * Helen: No.
     514 *
     515 * $stanzas = array(
     516 *     array(
     517 *         array(
     518 *             'time' => '',
     519 *             'author' => 'Scott',
     520 *             'messsage' => "Hey, let's chat!"
     521 *         ),
     522 *         array(
     523 *             'time' => '',
     524 *             'author' => 'Helen',
     525 *             'message' => 'No.'
     526 *         )
     527 *     )
     528 * )
     529 * @param string $content A string which might contain chat data.
     530 * @param boolean $remove Whether to remove the found data from the passed content.
     531 * @return array A chat log as structured data
     532 */
     533function get_content_chat( &$content, $remove = false ) {
     534        $trimmed = trim( $content );
     535        $newline_regex = '#^(\[.+?\])?\s?(?:(?:([^:]+):)|(?:<([^>]+)>))#';
     536
     537        if ( empty( $trimmed ) || ! preg_match( $newline_regex, $trimmed ) )
     538                return array();
     539
     540        $last_index = 0;
     541        $stanzas = array();
     542        $lines = explode( "\n", make_clickable( $trimmed ) );
     543
     544        $author = $time = '';
     545        $data = array();
     546        $stanza = array();
     547
     548        foreach ( $lines as $index => $line ) {
     549                $line = trim( $line );
     550
     551                if ( empty( $line ) ) {
     552                        if ( ! empty( $author ) ) {
     553                                $stanza[] = array(
     554                                        'time' => $time,
     555                                        'author' => $author,
     556                                        'message' => join( ' ', $data )
     557                                );
     558                        }
     559
     560                        $stanzas[] = $stanza;
     561                        $last_index = $index;
     562                        $stanza = array();
     563                        $author = $time = '';
     564                        $data = array();
     565                        $commentary = ! preg_match( '#[:]#', $lines[$index + 1] ) && ! preg_match( '#<[^>]+>#', $lines[$index + 1] );
     566                        if ( ! empty( $lines[$index + 1] ) && $commentary )
     567                                break;
     568                }
     569
     570                $matches = array();
     571                $matched = preg_match( $newline_regex, $line, $matches );
     572                if ( $matched && ( ! empty( $matches[1] ) || ! empty( $matches[3] ) || ! preg_match( '#\s#', $matches[2] ) ) ) {
     573                        if ( ! empty( $author ) ) {
     574                                $stanza[] = array(
     575                                        'time' => $time,
     576                                        'author' => $author,
     577                                        'message' => join( ' ', $data )
     578                                );
     579                                $data = array();
     580                        }
     581
     582                        $time = $matches[1];
     583                        $author = empty( $matches[3] ) ? $matches[2] : $matches[3];
     584                        $data[] = trim( str_replace( $matches[0], '', $line ) );
     585                } elseif ( preg_match( '#\S#', $line ) ) {
     586                        $data[] = $line;
     587                }
     588        }
     589
     590        if ( ! empty( $author ) ) {
     591                $stanza[] = array(
     592                        'time' => $time,
     593                        'author' => $author,
     594                        'message' => trim( join( ' ', $data ) )
     595                );
     596        }
     597
     598        if ( ! empty( $stanza ) )
     599                $stanzas[] = $stanza;
     600
     601        if ( $remove )
     602                $content = trim( join( "\n", array_slice( $lines, $last_index ) ) );
     603
     604        return $stanzas;
     605}
     606
     607/**
     608 * Retrieve structured chat data from the current or passed post
     609 *
     610 * @since 3.6.0
     611 *
     612 * @param int $id Optional. Post ID
     613 * @return array
     614 */
     615function get_the_chat( $id = 0 ) {
     616        $post = empty( $id ) ? get_post() : get_post( $id );
     617        if ( empty( $post ) )
     618                return array();
     619
     620        $data = get_content_chat( $post->post_content );
     621        if ( empty( $data ) )
     622                return array();
     623
     624        return $data;
     625}
  • wp-includes/post-template.php

    diff --git wp-includes/post-template.php wp-includes/post-template.php
    index 7117c33..aa37a9c 100644
    function wp_post_revision_title( $revision, $link = true ) { 
    13151315        $date = date_i18n( $datef, strtotime( $revision->post_modified ) );
    13161316        if ( $link && current_user_can( 'edit_post', $revision->ID ) && $link = get_edit_post_link( $revision->ID ) )
    13171317                $date = "<a href='$link'>$date</a>";
    1318        
     1318
    13191319        $revision_date_author = sprintf(
    13201320                '%s %s, %s %s (%s)',
    13211321                $gravatar,
  • wp-includes/script-loader.php

    diff --git wp-includes/script-loader.php wp-includes/script-loader.php
    index 84b76d3..bf3e4fb 100644
    function wp_default_scripts( &$scripts ) { 
    277277
    278278        $scripts->add( 'imgareaselect', "/wp-includes/js/imgareaselect/jquery.imgareaselect$suffix.js", array('jquery'), '0.9.8', 1 );
    279279
     280        $scripts->add( 'mediaelement', "/wp-includes/js/mediaelement/mediaelement-and-player$suffix.js", array('jquery'), '2.10.1', 1 );
     281        $scripts->add( 'wp-mediaelement', "/wp-includes/js/mediaelement/wp-mediaelement.js", array('mediaelement'), false, 1 );
     282
    280283        $scripts->add( 'password-strength-meter', "/wp-admin/js/password-strength-meter$suffix.js", array('jquery'), false, 1 );
    281284        did_action( 'init' ) && $scripts->localize( 'password-strength-meter', 'pwsL10n', array(
    282285                'empty' => __('Strength indicator'),
    function wp_default_styles( &$styles ) { 
    543546        $styles->add( 'media-views', "/wp-includes/css/media-views$suffix.css", array( 'buttons' ) );
    544547        $styles->add( 'buttons', "/wp-includes/css/buttons$suffix.css" );
    545548
     549        $styles->add( 'mediaelement', "/wp-includes/js/mediaelement/mediaelementplayer$suffix.css" );
     550        $styles->add( 'wp-mediaelement', "/wp-includes/js/mediaelement/wp-mediaelement.css", array( 'mediaelement' ) );
     551
    546552        foreach ( $rtl_styles as $rtl_style ) {
    547553                $styles->add_data( $rtl_style, 'rtl', true );
    548554                if ( $suffix && ! in_array( $rtl_style, $no_suffix ) )
  • wp-includes/shortcodes.php

    diff --git wp-includes/shortcodes.php wp-includes/shortcodes.php
    index bdc3f9b..b7a0b1b 100644
    function remove_all_shortcodes() { 
    128128}
    129129
    130130/**
     131 * Whether a registered shortcode exists named $tag
     132 *
     133 * @since 3.6.0
     134 *
     135 * @global array $shortcode_tags
     136 * @param string $tag
     137 * @return boolean
     138 */
     139function shortcode_exists( $tag ) {
     140        global $shortcode_tags;
     141        return array_key_exists( $tag, $shortcode_tags );
     142}
     143
     144/**
     145 * Whether the passed content contains the specified shortcode
     146 *
     147 * @since 3.6.0
     148 *
     149 * @global array $shortcode_tags
     150 * @param string $tag
     151 * @return boolean
     152 */
     153function has_shortcode( $content, $tag ) {
     154        if ( shortcode_exists( $tag ) ) {
     155                $matches = array();
     156                preg_match_all( '/' . get_shortcode_regex() . '/s', $content, $matches, PREG_SET_ORDER );
     157                if ( empty( $matches ) )
     158                        return false;
     159
     160                foreach ( $matches as $shortcode ) {
     161                        if ( $tag === $shortcode[2] )
     162                                return true;
     163                }
     164        }
     165        return false;
     166}
     167
     168/**
    131169 * Search content for shortcodes and filter shortcodes through their hooks.
    132170 *
    133171 * If there are no shortcode tags defined, then the content will be returned