WordPress.org

Make WordPress Core

Ticket #32417: 32417.6.diff

File 32417.6.diff, 18.9 KB (added by westonruter, 16 months ago)

https://github.com/xwp/wordpress-develop/pull/215

  • new file src/wp-includes/css/wp-media-widget.css

    diff --git src/wp-includes/css/wp-media-widget.css src/wp-includes/css/wp-media-widget.css
    new file mode 100644
    index 0000000000..ea6c75a342
    - +  
     1.media-widget-preview .button {
     2        text-align: center
     3}
     4
     5.media-widget-preview .aligncenter {
     6        display: block;
     7        margin: 0 auto;
     8        text-align: center
     9}
     10
     11.media-widget-preview .image {
     12        height: auto;
     13        max-width: 100%;
     14        cursor: pointer;
     15}
  • src/wp-includes/default-widgets.php

    diff --git src/wp-includes/default-widgets.php src/wp-includes/default-widgets.php
    index 0cf5fc336b..e803135871 100644
    require_once( ABSPATH . WPINC . '/widgets/class-wp-widget-tag-cloud.php' ); 
    4545
    4646/** WP_Nav_Menu_Widget class */
    4747require_once( ABSPATH . WPINC . '/widgets/class-wp-nav-menu-widget.php' );
     48
     49/** WP_Widget_Media class */
     50require_once( ABSPATH . WPINC . '/widgets/class-wp-widget-media.php' );
  • new file src/wp-includes/js/wp-media-widget.js

    diff --git src/wp-includes/js/wp-media-widget.js src/wp-includes/js/wp-media-widget.js
    new file mode 100644
    index 0000000000..cfed54b96a
    - +  
     1/**
     2 * @since 4.4.0
     3 *
     4 * @package WP_Media_Widget
     5 */
     6(function ( $ ) {
     7        var frame, widgetFrame;
     8
     9        frame = {
     10                buttonId: '.media-widget-preview .button',
     11
     12                defaultProps: {
     13                        'id' : '',
     14                        'align' : '',
     15                        'size' : '',
     16                        'link' : ''
     17                },
     18
     19                init: function() {
     20                        $( frame.buttonId )
     21                                .off( 'click.mediaWidget' )
     22                                .on( 'click.mediaWidget', frame.openMediaManager );
     23
     24                        frame.bindImageClick();
     25
     26                        wp.mediaelement.initialize();
     27                },
     28
     29                bindImageClick: function(){
     30                        $('.media-widget-preview .image')
     31                                .off( 'click.mediaWidget' )
     32                                .on( 'click.mediaWidget', frame.openMediaManager );
     33                },
     34
     35                openMediaManager: function( event ) {
     36                        event.preventDefault();
     37                        var widget_id = $( event.target ).data( 'id' );
     38
     39                        // Create the media frame.
     40                        widgetFrame = wp.media({
     41                                button: {
     42                                        text: 'Use as widget' // Text of the submit button.
     43                                },
     44
     45                                states: new wp.media.controller.Library({
     46                                        library:   wp.media.query(),
     47                                        title: 'Select Media', // Media frame title
     48                                        multiple:  false,
     49                                        priority:  20,
     50                                        display: true // attachment display setting
     51                                })
     52                        });
     53
     54                        // Populate previously selected media when the media frame is opened.
     55                        widgetFrame.on( 'open', function() {
     56                                var selection = widgetFrame.state().get('selection'),
     57                                        ids = $( '#widget-' + widget_id + '-id' ).val().split(',');
     58
     59                                if ( ids[0] > 0 ) {
     60                                        ids.forEach( function( id ) {
     61                                                var attachment = wp.media.attachment( id );
     62                                                attachment.fetch();
     63                                                selection.add( attachment ? [ attachment ] : [] );
     64                                        });
     65                                }
     66                        });
     67
     68                        // Render the attachment details.
     69                        widgetFrame.on( 'select', function() {
     70                                var props, attachment;
     71
     72                                // Only try to render the attachment details if a selection was made.
     73                                if ( widgetFrame.state().get('selection').length > 0 ) {
     74                                        props = widgetFrame.content.get('.attachments-browser')
     75                                                .sidebar.get('display').model.toJSON();
     76
     77                                        attachment = widgetFrame.state().get('selection').first().toJSON();
     78
     79                                        frame.renderFormView( widget_id, props, attachment );
     80                                }
     81                        });
     82
     83                        widgetFrame.open( widget_id );
     84                },
     85
     86                /**
     87                 * Renders the attachment details from the media modal into the widget.
     88                 *
     89                 * @param {String} widget_id Attachment Display Settings (align, link, size, etc).
     90                 * @param {Object} props Attachment Display Settings (align, link, size, etc).
     91                 * @param {Object} attachment Attachment Details (title, description, caption, url, sizes, etc).
     92                 */
     93                renderFormView: function( widget_id, props, attachment ) {
     94                        // Start with container elements for the widgets page, customizer controls, and customizer preview.
     95                        var mediaEl,
     96                                html,
     97                                extras,
     98                                template,
     99                                formView = $( '.' + widget_id + ', #customize-control-widget_' + widget_id + ', #' + widget_id );
     100
     101                        // The widget title bar doesn't update automatically on the Appearance > Widgets page. This fixes that problem.
     102                        formView.closest( '.widget' ).find( '.in-widget-title' ).html( ': ' + attachment.title );
     103
     104                        formView.find( '.attachment-description' )
     105                                [ attachment.description ? 'removeClass' : 'addClass' ]('hidden')
     106                                .html( attachment.description );
     107
     108                        extras = formView.find( '.extras' );
     109                        // Display a preview of the image in the widgets page and customizer controls.
     110                        extras.removeClass( 'hidden' );
     111
     112                        attachment.link = props.link;
     113                        attachment.size = props.size;
     114
     115                        if ( 'image' === attachment.type ) {
     116
     117                                if ( mediaEl && ! mediaEl.length ) {
     118                                        extras.before( '<div class="media-widget-admin-preview"><img class="image" /></div>' );
     119                                        mediaEl = formView.find( '.image' ); // @todo Variable is not used.
     120                                }
     121
     122                                html = $( '<img />' ).attr({
     123                                        'data-id': widget_id,
     124                                        'src':     attachment.sizes[ props.size ].url,
     125                                        'class':   'image align' + props.align,
     126                                        'title':   attachment.title,
     127                                        'alt':     attachment.alt,
     128                                        'width':   attachment.sizes[ props.size ].width,
     129                                        'height':  attachment.sizes[ props.size ].height
     130                                }).wrap('<div />').parent().html();
     131
     132                        } else if ( 'audio' === attachment.type ) {
     133
     134                                if( 'embed' === props.link ) {
     135                                        template = wp.media.template( 'wp-media-widget-audio' );
     136                                        html = template( {
     137                                                model: {
     138                                                        src: attachment.url
     139                                                }
     140                                        } );
     141                                } else {
     142                                        html = '<a href="#">' + attachment.title + '</a>';
     143                                }
     144
     145                        } else if ( 'video' === attachment.type ) {
     146
     147                                if( 'embed' === props.link ) {
     148                                        template = wp.media.template( 'wp-media-widget-video' );
     149                                        html = template( {
     150                                                model: {
     151                                                        src: attachment.url,
     152                                                        width: attachment.width,
     153                                                        height: attachment.height
     154                                                }
     155                                        } );
     156                                } else {
     157                                        html = '<a href="#">' + attachment.title + '</a>';
     158                                }
     159
     160                        }
     161
     162                        mediaEl = formView.find( '.media-widget-admin-preview' );
     163                        if ( mediaEl.length ) {
     164                                if ( html ) {
     165                                        mediaEl.html( html );
     166                                } else {
     167                                        mediaEl.remove();
     168                                }
     169                        } else if ( html ) {
     170                                extras.before( '<div class="media-widget-admin-preview">' +  html + '</div>' );
     171                        }
     172
     173                        if ( -1 < $.inArray( attachment.type, [ 'audio', 'video' ] ) ) {
     174                                wp.mediaelement.initialize();
     175                        } else if ( 'image' === attachment.type ) {
     176                                frame.bindImageClick();
     177                        }
     178
     179                        // Populate form fields with selection data from the media frame.
     180                        _.each( _.keys( frame.defaultProps ), function ( key ) {
     181                                formView.find( '#widget-' + widget_id + '-' + key ).val( attachment[ key ] ).trigger( 'change' );
     182                        } );
     183
     184                        // Trigger a sync to update the widget in the customizer preview.
     185                        formView.find( '#widget-' + widget_id + '-url' ).trigger( 'change' );
     186                }
     187        };
     188
     189        $( document )
     190                .ready( frame.init )
     191                .on( 'widget-added widget-updated', frame.init );
     192
     193        window.wp = window.wp || {};
     194        window.wp.MediaWidget = frame;
     195})( jQuery );
  • src/wp-includes/widgets.php

    diff --git src/wp-includes/widgets.php src/wp-includes/widgets.php
    index 1abadfb186..f046f2dbef 100644
    function wp_widgets_init() { 
    14661466
    14671467        register_widget('WP_Nav_Menu_Widget');
    14681468
     1469        register_widget('WP_Media_Widget');
     1470
    14691471        /**
    14701472         * Fires after all default WordPress widgets have been registered.
    14711473         *
  • new file src/wp-includes/widgets/class-wp-widget-media.php

    diff --git src/wp-includes/widgets/class-wp-widget-media.php src/wp-includes/widgets/class-wp-widget-media.php
    new file mode 100644
    index 0000000000..0fbb9ebb9b
    - +  
     1<?php
     2/**
     3 * Widget API: WP_Media_Widget class
     4 *
     5 * @package WordPress
     6 * @subpackage Widgets
     7 * @since 4.4.0
     8 */
     9
     10/**
     11 * Core class that implements a media widget.
     12 *
     13 * @since 4.4.0
     14 *
     15 * @see WP_Widget
     16 */
     17class WP_Media_Widget extends WP_Widget {
     18        /**
     19         * Constructor.
     20         *
     21         * @since 4.4.0
     22         * @access public
     23         *
     24         * @param string $id_base         Optional Base ID for the widget, lowercase and unique. If left empty,
     25         *                                a portion of the widget's class name will be used Has to be unique.
     26         * @param string $name            Optional. Name for the widget displayed on the configuration page.
     27         *                                Default empty.
     28         * @param array  $widget_options  Optional. Widget options. See wp_register_sidebar_widget() for
     29         *                                information on accepted arguments. Default empty array.
     30         * @param array  $control_options Optional. Widget control options. See wp_register_widget_control()
     31         *                                for information on accepted arguments. Default empty array.
     32         */
     33        public function __construct( $id_base = '', $name = '', $widget_options = array(), $control_options = array() ) {
     34                $widget_opts = wp_parse_args( $widget_options, array(
     35                        'classname' => 'widget_media',
     36                        'description' => __( 'Display media in your sidebar.' ),
     37                        'customize_selective_refresh' => true,
     38                ) );
     39
     40                $control_opts = wp_parse_args( $control_options, array() );
     41
     42                parent::__construct(
     43                        $id_base ? $id_base : 'wp-media-widget',
     44                        $name ? $name : __( 'Media' ),
     45                        $widget_opts,
     46                        $control_opts
     47                );
     48
     49                add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_admin_styles' ) );
     50                add_action( 'admin_enqueue_scripts', array( $this, 'enqueue_admin_scripts' ) );
     51        }
     52
     53        /**
     54         * Displays the widget on the front-end.
     55         *
     56         * @since 4.4.0
     57         * @access public
     58         *
     59         * @see WP_Widget::widget()
     60         *
     61         * @param array $args     Display arguments including before_title, after_title, before_widget, and after_widget.
     62         * @param array $instance Saved setting from the database.
     63         */
     64        public function widget( $args, $instance ) {
     65                extract( $instance );
     66
     67                echo $args['before_widget'];
     68                if ( ! empty( $instance['title'] ) ) {
     69                        echo $args['before_title'] . $instance['title'] . $args['after_title'];
     70                }
     71                if ( ! empty( $instance['description'] ) ) {
     72                        echo '<p class="attachment-description align' . $instance['align'] . '">' . $instance['description'] . '</p>';
     73                }
     74                if ( ! empty( $instance['link'] ) ) {
     75                        if ( 'file' == $instance['link'] ) {
     76                                $url = wp_get_attachment_url( $instance['id'] );
     77                                $selectedLink = $url;
     78                        } else if ( 'post' == $instance['link'] ) {
     79                                $url = get_attachment_link( $instance['id'] );
     80                                $selectedLink = $url;
     81                        } else {
     82                                $selectedLink = '';
     83                        }
     84                }
     85
     86                // Build the media output.
     87                $media_output = '';
     88                if ( ! empty( $selectedLink ) ) {
     89                                $media_output .= '<a href="' . $selectedLink . '"';
     90                        if ( 'on' == $instance['target'] ) {
     91                                $media_output .= ' target="_blank"';
     92                        }
     93                        $media_output .= '>';
     94                }
     95
     96                if ( ! empty( $instance['id'] ) ) {
     97                        if ( $attachment = get_post( $instance['id'] ) ) {
     98                                // Image.
     99                                if ( wp_attachment_is_image( $attachment ) ) {
     100
     101                                        $media_output .= wp_get_attachment_image( $instance['id'], $instance['size'], false, array(
     102                                                'data-id' => esc_attr( $args['widget_id'] ),
     103                                                'class' => 'image align' . $instance['align'],
     104                                                'title' => $instance['title'],
     105                                        ) );
     106
     107                                // Audio.
     108                                } elseif ( wp_attachment_is( 'audio', $attachment ) ) {
     109                                        if ( ! empty( $selectedLink ) ) {
     110                                                $media_output .= $attachment->post_title;
     111                                        } else {
     112                                                $media_output .= wp_audio_shortcode( array(
     113                                                        'src' => wp_get_attachment_url( $attachment->ID )
     114                                                ) );
     115                                        }
     116
     117                                // Video.
     118                                } elseif( wp_attachment_is( 'video', $attachment ) ) {
     119                                        if ( ! empty( $selectedLink ) ) {
     120                                                $media_output .= $attachment->post_title;
     121                                        } else {
     122                                                $media_output .= wp_video_shortcode( array(
     123                                                        'src' => wp_get_attachment_url( $attachment->ID )
     124                                                ) );
     125                                        }
     126                                }
     127                        }
     128                }
     129
     130                if ( ! empty( $selectedLink ) ) {
     131                        $media_output .= '</a>';
     132                }
     133
     134                echo $media_output;
     135                echo $args['after_widget'];
     136        }
     137
     138        /**
     139         * Sanitizes the widget form values as they are saved.
     140         *
     141         * @since 4.4.0
     142         * @access public
     143         *
     144         * @see WP_Widget::update()
     145         *
     146         * @param array $new_instance Values just sent to be saved.
     147         * @param array $old_instance Previously saved values from database.
     148         * @return array Updated safe values to be saved.
     149         */
     150        function update( $new_instance, $old_instance ) {
     151                $instance = $old_instance;
     152
     153                // ID, title, target.
     154                $instance['id'] = (int) $new_instance['id'];
     155                $instance['title'] = sanitize_text_field( $new_instance['title'] );
     156                $instance['target'] = isset( $new_instance['target'] ) ? sanitize_text_field( $new_instance['target'] ) : '';
     157
     158                // Everything else.
     159                $instance['align'] = sanitize_text_field( $new_instance['align'] );
     160                $instance['size'] = sanitize_text_field( $new_instance['size'] );
     161                $instance['link'] = sanitize_text_field( $new_instance['link'] );
     162                return $instance;
     163        }
     164
     165        /**
     166         * Renders an image attachment preview.
     167         *
     168         * @since 4.4.0
     169         * @access public
     170         *
     171         * @param WP_Post $attachment Attachment object.
     172         * @param string  $widget_id  Widget ID.
     173         * @param array   $instance   Current widget instance arguments.
     174         */
     175        public function render_image( $attachment, $widget_id, $instance ) {
     176                // If an image id is saved for this widget, display the image using `wp_get_attachment_image()`.
     177                echo '<p class="media-widget-admin-preview">',
     178                        wp_get_attachment_image( $attachment->ID, $instance['size'], false, array(
     179                                'data-id' => esc_attr( $widget_id ),
     180                                'class'   => 'image align' . esc_attr( $instance['align'] ),
     181                                'title'   => esc_attr( $instance['title'] ),
     182                        ) ),
     183                '</p>';
     184        }
     185
     186        /**
     187         * Renders an audio attachment preview.
     188         *
     189         * @since 4.4.0
     190         * @access public
     191         *
     192         * @param WP_Post $attachment Attachment object.
     193         * @param string  $widget_id  Widget ID.
     194         * @param array   $instance   Current widget instance arguments.
     195         */
     196        public function render_audio( $attachment, $widget_id, $instance ) {
     197                echo '<p class="media-widget-admin-preview">';
     198                if( $instance['link'] == 'embed' ){
     199                        echo wp_audio_shortcode( array(
     200                                'src' => wp_get_attachment_url( $attachment->ID )
     201                        ) );
     202                } else {
     203                        echo '<a href="#">' . $attachment->post_title .'</a>';
     204                }
     205                echo '</p>';
     206        }
     207
     208        /**
     209         * Renders a video attachment preview.
     210         *
     211         * @since 4.4.0
     212         * @access public
     213         *
     214         * @param WP_Post $attachment Attachment object.
     215         * @param string  $widget_id  Widget ID.
     216         * @param array   $instance   Current widget instance arguments.
     217         */
     218        public function render_video( $attachment, $widget_id, $instance ) {
     219                echo '<p class="media-widget-admin-preview">';
     220                if( $instance['link'] == 'embed' ){
     221                        echo wp_video_shortcode( array(
     222                                'src' => wp_get_attachment_url( $attachment->ID )
     223                        ) );
     224                } else {
     225                        echo '<a href="#">' . $attachment->post_title .'</a>';
     226                }
     227                echo '</p>';
     228        }
     229
     230        /**
     231         * Outputs the settings update form.
     232         *
     233         * @since 4.4.0
     234         * @access public
     235         *
     236         * @param array $saved_instance Current settings.
     237         * @return string Default return is 'noform'.
     238         */
     239        public function form( $saved_instance ) {
     240                $defaults = array(
     241                        'title'  => '',
     242                        'target' => '',
     243                        // Attachment props.
     244                        'id'     => '',
     245                        'align'  => '',
     246                        'size'   => '',
     247                        'link'   => '',
     248                );
     249                $instance = wp_parse_args( (array) $saved_instance, $defaults );
     250                $widget_id = $this->id;
     251                ?>
     252                <div class="<?php echo esc_attr( $widget_id ); ?> media-widget-preview">
     253                        <p>
     254                                <label for="<?php echo $this->get_field_id( 'title' ); ?>"><?php esc_html_e( 'Title:' ); ?></label>
     255                                <input class="widefat" id="<?php echo $this->get_field_id( 'title' ); ?>" name="<?php echo $this->get_field_name( 'title' ); ?>" type="text" value="<?php echo esc_attr( $instance['title'] ); ?>" />
     256                        </p>
     257
     258                        <p>
     259                                <?php _e( 'Add an image, gallery, video, or audio to your sidebar.' ); ?>
     260                        </p>
     261
     262                        <p>
     263                                <a data-id="<?php echo esc_attr( $widget_id ); ?>" class="button select-media widefat"><?php
     264                                        esc_html_e( 'Select Media' );
     265                                ?></a>
     266                        </p>
     267
     268                        <?php
     269                        if ( ! empty( $instance['id'] ) ) {
     270
     271                                $attachment = get_post( $instance['id'] );
     272                                if ( $attachment ) {
     273                                        if ( wp_attachment_is_image( $attachment ) ) {
     274                                                $this->render_image( $attachment, $widget_id, $instance );
     275                                        } elseif ( wp_attachment_is( 'audio', $attachment ) ) {
     276                                                $this->render_audio( $attachment, $widget_id, $instance );
     277                                        } elseif ( wp_attachment_is( 'video', $attachment ) ) {
     278                                                $this->render_video( $attachment, $widget_id, $instance );
     279                                        }
     280                                }
     281                        }
     282                        ?>
     283
     284                        <p class="extras<?php echo empty( $instance['id'] ) ? ' hidden' : ''; ?>">
     285                                <input type="checkbox" name="<?php echo esc_attr( $this->get_field_name( 'target' ) ); ?>" id="<?php echo esc_attr( $this->get_field_id( 'target' ) ); ?>"
     286                                        <?php
     287                                        if ( ! empty( $instance['target'] ) ) {
     288                                                checked( 'on', $instance['target'] );
     289                                        }
     290                                        ?> />
     291                                <label for="<?php echo esc_attr( $this->get_field_id( 'target' ) ); ?>">
     292                                        <?php esc_html_e( 'Open link in a new tab or window' ); ?>
     293                                </label>
     294                        </p>
     295
     296                        <fieldset class="media-widget-hidden-fields">
     297                                <?php
     298                                // Use hidden form fields to capture the attachment details from the media manager.
     299                                unset( $instance['title'] );
     300                                unset( $instance['target'] );
     301                                ?>
     302
     303                                <?php foreach ( array_keys( $instance ) as $i ) : ?>
     304                                        <input type="hidden" id="<?php echo esc_attr( $this->get_field_id( $i ) ); ?>" name="<?php echo esc_attr( $this->get_field_name( $i ) ); ?>" value="<?php echo esc_attr( $instance[ $i ] ); ?>" />
     305                                <?php endforeach; ?>
     306                        </fieldset>
     307                </div>
     308                <?php
     309        }
     310
     311        /**
     312         * Registers the stylesheet for handling the widget in the back-end.
     313         *
     314         * @since 4.4.0
     315         * @access public
     316         */
     317        public function enqueue_admin_styles() {
     318                wp_enqueue_style( 'wp-media-widget-styles', includes_url( 'css/wp-media-widget.css' ), array( 'media-views' ) );
     319        }
     320
     321        /**
     322         * Registers the scripts for handling the widget in the back-end.
     323         *
     324         * @since 4.4.0
     325         * @access public
     326         */
     327        public function enqueue_admin_scripts() {
     328                global $pagenow;
     329
     330                // Bail if we are not in the widgets or customize screens.
     331                if ( ! ( 'widgets.php' == $pagenow || 'customize.php' == $pagenow ) ) {
     332                        return;
     333                }
     334
     335                // Load the required media files for the media manager.
     336                wp_enqueue_media();
     337
     338                // Register, localize and enqueue custom JS.
     339                wp_enqueue_script(
     340                        'wp-media-widget',
     341                        includes_url( 'js/wp-media-widget.js' ),
     342                        array( 'jquery', 'media-models', 'media-views' ),
     343                        '',
     344                        true
     345                );
     346
     347                wp_localize_script( 'wp-media-widget', '_mediaWidgetl10n',
     348                        array(
     349                                'title'  => __( 'Select an Image' ),
     350                                'button' => __( 'Insert Image' )
     351                        )
     352                );
     353
     354                add_action( 'admin_print_footer_scripts', array( $this, 'admin_print_footer_scripts' ) );
     355        }
     356
     357        /**
     358         * Prints footer scripts.
     359         *
     360         * @since 4.4.0
     361         * @access public
     362         */
     363        public function admin_print_footer_scripts() {
     364                ?>
     365                <script type="text/html" id="tmpl-wp-media-widget-audio">
     366                <?php wp_underscore_audio_template() ?>
     367                </script>
     368
     369                <script type="text/html" id="tmpl-wp-media-widget-video">
     370                <?php wp_underscore_video_template() ?>
     371                </script>
     372
     373                <?php
     374        }
     375}