From 0421a2b0a46ae01ff56a4ab03ad825c9fa95555a Mon Sep 17 00:00:00 2001 From: Weston Ruter Date: Thu, 19 Oct 2017 00:06:25 +0000 Subject: [PATCH] Widgets: Harden logic for checking for valid media URLs. * Update deprecated `isHostedVideo` method to always return `true` since all oEmbeds are now supported. * Disable `scanImage` for non-image media widgets. * Ensure embed URL field element is matched from current media frame instance due to bug where media frames are not destroyed upon closing. * Update error message for invalid video URLs to ask user to check the URL for validity. Props gk.loveweb, octalmage, westonruter. See #42039, #40935. Fixes #41052. git-svn-id: https://develop.svn.wordpress.org/trunk@41933 602fd350-edb4-49c9-b593-d223f7449a82 --- src/wp-admin/js/widgets/media-video-widget.js | 3 +- src/wp-admin/js/widgets/media-widgets.js | 58 +++++++++++++++---- .../widgets/class-wp-widget-media-video.php | 2 +- 3 files changed, 50 insertions(+), 13 deletions(-) diff --git a/src/wp-admin/js/widgets/media-video-widget.js b/src/wp-admin/js/widgets/media-video-widget.js index 4af062054d..ddaaf5f3f5 100644 --- a/src/wp-admin/js/widgets/media-video-widget.js +++ b/src/wp-admin/js/widgets/media-video-widget.js @@ -138,11 +138,10 @@ * * @deprecated since 4.9. * - * @param {String} url - Video url. * @returns {boolean} Whether url is a supported video host. */ isHostedVideo: function isHostedVideo() { - return false; + return true; }, /** diff --git a/src/wp-admin/js/widgets/media-widgets.js b/src/wp-admin/js/widgets/media-widgets.js index ad21e37a7e..b8e8d5dc65 100644 --- a/src/wp-admin/js/widgets/media-widgets.js +++ b/src/wp-admin/js/widgets/media-widgets.js @@ -84,6 +84,23 @@ wp.mediaWidgets = ( function( $ ) { */ component.MediaEmbedView = wp.media.view.Embed.extend({ + /** + * Initialize. + * + * @since 4.9.0 + * + * @param {object} options - Options. + * @returns {void} + */ + initialize: function( options ) { + var view = this, embedController; // eslint-disable-line consistent-thi + wp.media.view.Embed.prototype.initialize.call( view, options ); + if ( 'image' !== view.controller.options.mimeType ) { + embedController = view.controller.states.get( 'embed' ); + embedController.off( 'scan', embedController.scanImage, embedController ); + } + }, + /** * Refresh embed view. * @@ -139,6 +156,33 @@ wp.mediaWidgets = ( function( $ ) { } }, + /** + * Update oEmbed. + * + * @since 4.9.0 + * + * @returns {void} + */ + updateoEmbed: function() { + var embedLinkView = this, url; // eslint-disable-line consistent-this + + url = embedLinkView.model.get( 'url' ); + + // Abort if the URL field was emptied out. + if ( ! url ) { + embedLinkView.setErrorNotice( '' ); + embedLinkView.setAddToWidgetButtonDisabled( true ); + return; + } + + if ( ! url.match( /^(http|https):\/\/.+\// ) ) { + embedLinkView.controller.$el.find( '#embed-url-field' ).addClass( 'invalid' ); + embedLinkView.setAddToWidgetButtonDisabled( true ); + } + + wp.media.view.EmbedLink.prototype.updateoEmbed.call( embedLinkView ); + }, + /** * Fetch media. * @@ -146,17 +190,12 @@ wp.mediaWidgets = ( function( $ ) { */ fetch: function() { var embedLinkView = this, fetchSuccess, matches, fileExt, urlParser, url, re, youTubeEmbedMatch; // eslint-disable-line consistent-this + url = embedLinkView.model.get( 'url' ); if ( embedLinkView.dfd && 'pending' === embedLinkView.dfd.state() ) { embedLinkView.dfd.abort(); } - // Abort if the URL field was emptied out. - if ( ! embedLinkView.model.get( 'url' ) ) { - embedLinkView.setErrorNotice( '' ); - return; - } - fetchSuccess = function( response ) { embedLinkView.renderoEmbed({ data: { @@ -164,13 +203,13 @@ wp.mediaWidgets = ( function( $ ) { } }); - $( '#embed-url-field' ).removeClass( 'invalid' ); + embedLinkView.controller.$el.find( '#embed-url-field' ).removeClass( 'invalid' ); embedLinkView.setErrorNotice( '' ); embedLinkView.setAddToWidgetButtonDisabled( false ); }; urlParser = document.createElement( 'a' ); - urlParser.href = embedLinkView.model.get( 'url' ); + urlParser.href = url; matches = urlParser.pathname.toLowerCase().match( /\.(\w+)$/ ); if ( matches ) { fileExt = matches[1]; @@ -185,7 +224,6 @@ wp.mediaWidgets = ( function( $ ) { } // Support YouTube embed links. - url = embedLinkView.model.get( 'url' ); re = /https?:\/\/www\.youtube\.com\/embed\/([^/]+)/; youTubeEmbedMatch = re.exec( url ); if ( youTubeEmbedMatch ) { @@ -228,7 +266,7 @@ wp.mediaWidgets = ( function( $ ) { */ renderFail: function renderFail() { var embedLinkView = this; // eslint-disable-line consistent-this - $( '#embed-url-field' ).addClass( 'invalid' ); + embedLinkView.controller.$el.find( '#embed-url-field' ).addClass( 'invalid' ); embedLinkView.setErrorNotice( embedLinkView.controller.options.invalidEmbedTypeError || 'ERROR' ); embedLinkView.setAddToWidgetButtonDisabled( true ); } diff --git a/src/wp-includes/widgets/class-wp-widget-media-video.php b/src/wp-includes/widgets/class-wp-widget-media-video.php index b129527d84..96196e60f9 100644 --- a/src/wp-includes/widgets/class-wp-widget-media-video.php +++ b/src/wp-includes/widgets/class-wp-widget-media-video.php @@ -41,7 +41,7 @@ class WP_Widget_Media_Video extends WP_Widget_Media { 'media_library_state_multi' => _n_noop( 'Video Widget (%d)', 'Video Widget (%d)' ), 'media_library_state_single' => __( 'Video Widget' ), /* translators: %s: a list of valid video file extensions */ - 'unsupported_file_type' => sprintf( __( 'Sorry, we can’t display the video file type selected. Please select a supported video file (%s) or stream (e.g. YouTube and Vimeo) instead.' ), '.' . implode( ', .', wp_get_video_extensions() ) . '' ), + 'unsupported_file_type' => sprintf( __( 'Sorry, we can’t load the video at the supplied URL. Please check that the URL is for a supported video file (%s) or stream (e.g. YouTube and Vimeo).' ), '.' . implode( ', .', wp_get_video_extensions() ) . '' ), ) ); }