From 0231af0be3b4f06832f29dc8505334fd81648a7f Mon Sep 17 00:00:00 2001 From: David Binovec Date: Fri, 9 Sep 2016 16:18:17 +0000 Subject: [PATCH 1/2] Adding a new class for properly handling Instagram oembeds in previews Since the WordPress is calling the `make_clickable` function in terms of the `comment_text` filter, Instagram oEmbedes containing a plaintext link are not being properly initialised as Instagram's JS expects only a single `a` element inside the `blockquote`. This commit is programmatically removing the script element using DomDocument and is appending a custom one, which 1) load the original script only if it has not been loaded before 2) initialise the Instagram oEmbed manually (as a side effect this fixes the issue with Instagram oEmbeds not properly working when clicking the preview button multiple times). --- ...-wpcom-liveblog-entry-instagram-oembed.php | 81 +++++++++++++++++++ liveblog.php | 2 + 2 files changed, 83 insertions(+) create mode 100644 classes/class-wpcom-liveblog-entry-instagram-oembed.php diff --git a/classes/class-wpcom-liveblog-entry-instagram-oembed.php b/classes/class-wpcom-liveblog-entry-instagram-oembed.php new file mode 100644 index 000000000..82266215b --- /dev/null +++ b/classes/class-wpcom-liveblog-entry-instagram-oembed.php @@ -0,0 +1,81 @@ +get_provider( $url ); + if ( false !== strpos( 'instagr.am' ) || false !== strpos( 'instagram.com' ) ) { + $html = self::instagram_handler( $html, $url, $attr, $post_ID ); + } + + return $html; + + } + + /** + * The custom modifications themselves + * + * This method is removing the default script and attaches it's own + */ + public static function instagram_handler( $html, $url, $attr, $post_ID ) { + $instagram_script_uri = '//platform.instagram.com/en_US/embeds.js'; + $dom = new DOMDocument(); + $dom->loadHTML( $html, LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD ); + $script = $dom->getElementsByTagName( 'script' ); + + $new_script = $dom->createElement( 'script', '(function( $ ){ if ( undefined === window.instgrm ) { $.getScript( '.wp_json_encode( $instagram_script_uri ).' ); } $(".instagram-media a").each( function(){ if ( -1 === $(this).attr("href").indexOf("instagr") ) { $(this).replaceWith( $(this).text() ) } } ); window.instgrm.Embeds.process(); })(jQuery);' ); + $new_script->setAttribute( 'type', 'text/javascript' ); + + if ( false === empty( $script ) ) { + foreach( $script as $item ) { + if ( $instagram_script_uri === $item->getAttribute('src') ) { + $parent = $item->parentNode; + $item->parentNode->removeChild($item); + $parent->appendChild( $new_script ); + break; + } + } + } + $html = $dom->saveHTML(); + return $html; + } +} diff --git a/liveblog.php b/liveblog.php index 4c40ffb66..d27284793 100644 --- a/liveblog.php +++ b/liveblog.php @@ -82,6 +82,7 @@ public static function load() { WPCOM_Liveblog_Entry_Extend::load(); WPCOM_Liveblog_Lazyloader::load(); WPCOM_Liveblog_Socketio_Loader::load(); + WPCOM_Liveblog_Entry_Instagram_oEmbed::load(); } public static function add_custom_post_type_support( $query ) { @@ -122,6 +123,7 @@ private static function includes() { require( dirname( __FILE__ ) . '/classes/class-wpcom-liveblog-entry-extend-feature-authors.php' ); require( dirname( __FILE__ ) . '/classes/class-wpcom-liveblog-lazyloader.php' ); require( dirname( __FILE__ ) . '/classes/class-wpcom-liveblog-socketio-loader.php' ); + require( dirname( __FILE__ ) . '/classes/class-wpcom-liveblog-entry-instagram-oembed.php' ); // Manually include ms.php theme-side in multisite environments because // we need its filesize and available space functions. From 2a13320c37a0b28f0a3a4d62387c84d470aa07ed Mon Sep 17 00:00:00 2001 From: David Binovec Date: Tue, 13 Sep 2016 11:30:03 +0000 Subject: [PATCH 2/2] Improved Instagram oembed class This commit removes the DOM Document parsing of the oEmbed response in favour of taking advantage of `oembed_fetch_url` filter for requesting the oEmbed without the script --- ...-wpcom-liveblog-entry-instagram-oembed.php | 60 +++++++------------ 1 file changed, 21 insertions(+), 39 deletions(-) diff --git a/classes/class-wpcom-liveblog-entry-instagram-oembed.php b/classes/class-wpcom-liveblog-entry-instagram-oembed.php index 82266215b..84eb83206 100644 --- a/classes/class-wpcom-liveblog-entry-instagram-oembed.php +++ b/classes/class-wpcom-liveblog-entry-instagram-oembed.php @@ -22,8 +22,8 @@ public static function load() { */ public static function register_filters( $return ) { - add_filter( 'embed_oembed_html', array( __CLASS__, 'filter_oembed_html' ), 10, 4 ); - //Deregister the filter as soon as it is no longer needed + add_filter( 'oembed_fetch_url', array( __CLASS__, 'add_omitscript_arg' ), 10, 3 ); + add_filter( 'embed_oembed_html', array( __CLASS__, 'add_custom_script' ), 10, 4 ); add_filter( 'comment_text', array( __CLASS__, 'unregister_filters' ), 0, 1 ); return $return; } @@ -32,50 +32,32 @@ public static function register_filters( $return ) { * Deregister the filter we added */ public static function unregister_filters( $return ) { - remove_filter( 'embed_oembed_html', array( __CLASS__, 'filter_oembed_html' ) ); + remove_filter( 'oembed_fetch_url', array( __CLASS__, 'add_omitscript_arg' ), 10 ); + remove_filter( 'embed_oembed_html', array( __CLASS__, 'add_custom_script' ), 10 ); return $return; } - /** - * Filter the oEmbed HTML only if instagram is the provider - */ - public static function filter_oembed_html( $html, $url, $attr, $post_ID ) { - - $oembed = _wp_oembed_get_object(); - $provider = $oembed->get_provider( $url ); - if ( false !== strpos( 'instagr.am' ) || false !== strpos( 'instagram.com' ) ) { - $html = self::instagram_handler( $html, $url, $attr, $post_ID ); + public static function add_omitscript_arg( $provider, $url, $args ) { + if ( true === self::is_instagram_provider( $url ) ) { + $provider = add_query_arg( 'omitscript', rawurlencode( true ), $provider ); } - - return $html; - + return $provider; } - /** - * The custom modifications themselves - * - * This method is removing the default script and attaches it's own - */ - public static function instagram_handler( $html, $url, $attr, $post_ID ) { - $instagram_script_uri = '//platform.instagram.com/en_US/embeds.js'; - $dom = new DOMDocument(); - $dom->loadHTML( $html, LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD ); - $script = $dom->getElementsByTagName( 'script' ); - - $new_script = $dom->createElement( 'script', '(function( $ ){ if ( undefined === window.instgrm ) { $.getScript( '.wp_json_encode( $instagram_script_uri ).' ); } $(".instagram-media a").each( function(){ if ( -1 === $(this).attr("href").indexOf("instagr") ) { $(this).replaceWith( $(this).text() ) } } ); window.instgrm.Embeds.process(); })(jQuery);' ); - $new_script->setAttribute( 'type', 'text/javascript' ); - - if ( false === empty( $script ) ) { - foreach( $script as $item ) { - if ( $instagram_script_uri === $item->getAttribute('src') ) { - $parent = $item->parentNode; - $item->parentNode->removeChild($item); - $parent->appendChild( $new_script ); - break; - } - } + public static function add_custom_script( $html, $url, $attr, $post_ID ) { + if ( true === self::is_instagram_provider( $url ) ) { + $instagram_script_uri = '//platform.instagram.com/en_US/embeds.js'; + $script = ''; + $html .= $script; } - $html = $dom->saveHTML(); return $html; } + + private static function is_instagram_provider( $url ) { + $wp_oembed = _wp_oembed_get_object(); + $provider = $wp_oembed->get_provider( $url ); + return ( 'https://api.instagram.com/oembed' === $provider ); + } }