diff --git a/inc/shortcodes/class-instagram.php b/inc/shortcodes/class-instagram.php index 922f232..94a9b43 100644 --- a/inc/shortcodes/class-instagram.php +++ b/inc/shortcodes/class-instagram.php @@ -15,6 +15,12 @@ public static function get_shortcode_ui_args() { 'type' => 'text', 'description' => esc_html__( 'URL to an Instagram', 'shortcake-bakery' ), ), + array( + 'label' => esc_html__( 'Hide Caption', 'shortcake-bakery' ), + 'attr' => 'hidecaption', + 'type' => 'checkbox', + 'description' => esc_html__( 'By default, the Instagram embed will include the caption. Check this box to hide the caption.', 'shortcake-bakery' ), + ), ), ); } @@ -55,21 +61,48 @@ public static function reversal( $content ) { } public static function callback( $attrs, $content = '' ) { + global $content_width; if ( empty( $attrs['url'] ) ) { return ''; } - $needle = '#(https?:)?//instagr(\.am|am\.com)/p/([^/]+)#i'; - if ( preg_match( $needle, $attrs['url'], $matches ) ) { - $photo_id = $matches[3]; - } else { - return ''; + $max_width = 698; + $min_width = 320; + + $defaults = array( + 'width' => isset( $content_width ) ? $content_width : $max_width, + 'hidecaption' => false, + ); + $attrs = array_merge( $defaults, $attrs ); + + $attrs['width'] = absint( $attrs['width'] ); + if ( $attrs['width'] > $max_width || $min_width > $attrs['width'] ) { + $attrs['width'] = $max_width; } - return sprintf( '', - esc_url( sprintf( 'https://instagram.com/p/%s/embed/', $photo_id ) ) + $url_args = array( + 'width' => $attrs['width'], ); + + if ( $attrs['hidecaption'] ) { + $url_args['hidecaption'] = 'true'; + // Filter oembed_fetch_url to tell the Instagram API to hide the caption + add_filter( 'oembed_fetch_url', function( $provider, $url, $args ) { + $provider = add_query_arg( 'hidecaption', 'true', $provider ); + return $provider; + }, 10, 3 ); + } + + $html = self::get_oembed_html( $attrs['url'], $url_args ); + + if ( ! empty( $html ) ) { + wp_enqueue_script( 'shortcake-bakery-instagram', '//platform.instagram.com/en_US/embeds.js', array( 'jquery' ), false, true ); + // there's a script in the response, which we strip on purpose since it's added by this ^ script + $html = preg_replace( '@<(script)[^>]*?>.*?\\1>@si', '', $html ); + return $html; + } + return ''; } } diff --git a/inc/shortcodes/class-shortcode.php b/inc/shortcodes/class-shortcode.php index bb94963..4cd827f 100644 --- a/inc/shortcodes/class-shortcode.php +++ b/inc/shortcodes/class-shortcode.php @@ -176,4 +176,71 @@ protected static function make_replacements_to_content( $content, $replacements return str_replace( array_keys( $replacements ), array_values( $replacements ), $content ); } + /** + * Get embed HTML using oEmbed, using cache if available + * + * @param string $url URL + * @param array $args URL args. Optional. + * @return string Embed HTML + */ + protected static function get_oembed_html( $url, $args = array() ) { + global $post; + $post_id = $post->ID; + $tag = self::get_shortcode_tag(); + + if ( empty( $post_id ) || empty( $url ) ) { + return; + } + + // Check for a cached result (stored in the post meta) + $key_prefix = "_shortcake_bakery_{$tag}_oembed_"; + $key_suffix = md5( $url . serialize( $args ) ); + $cachekey = $key_prefix . $key_suffix; + $cachekey_time = $key_prefix . 'time_' . $key_suffix; + + /** + * Filter the oEmbed TTL value (time to live). + * + * @param int $time Time to live (in seconds). + * @param array $attr An array of shortcode attributes. + * @param int $post_id Post ID. + */ + $ttl = apply_filters( 'shortcake_bakery_oembed_ttl', DAY_IN_SECONDS, $args, $post_id ); + + $cache = get_post_meta( $post_id, $cachekey, true ); + $cache_time = get_post_meta( $post_id, $cachekey_time, true ); + + if ( ! $cache_time ) { + $cache_time = 0; + } + + $cached_recently = ( time() - $cache_time ) < $ttl; + + if ( $cached_recently ) { + // Failures are cached. Return if we're using the cache. + if ( '{{unknown}}' === $cache ) { + return; + } + + if ( ! empty( $cache ) ) { + return $cache; + } + } + + $html = wp_oembed_get( $url, $args ); + + // Maybe cache the result + if ( $html ) { + update_post_meta( $post_id, $cachekey, $html ); + update_post_meta( $post_id, $cachekey_time, time() ); + } elseif ( ! $cache ) { + update_post_meta( $post_id, $cachekey, '{{unknown}}' ); + } + + // If there was a result, return it + if ( $html ) { + return $html; + } + } + } diff --git a/tests/test-instagram-shortcode.php b/tests/test-instagram-shortcode.php index 4b7fae9..2f9a765 100644 --- a/tests/test-instagram-shortcode.php +++ b/tests/test-instagram-shortcode.php @@ -3,16 +3,16 @@ class Test_Instagram_Shortcode extends WP_UnitTestCase { public function test_post_display() { - $post_id = $this->factory->post->create( array( 'post_content' => '[instagram url="https://instagram.com/p/3QcZmWP5To/"]' ) ); + $post_id = $this->factory->post->create( array( 'post_content' => '[instagram url="https://instagram.com/p/r7Rl2el1ck/"]' ) ); $post = get_post( $post_id ); - $this->assertContains( '', apply_filters( 'the_content', $post->post_content ) ); + $this->assertContains( '', apply_filters( 'the_content', $post->post_content ) ); } public function test_embed_reversal() { $old_content = << Live footage!!! Toscana apartments in Irvine A video posted by TT ð (@teyent_theequeenb) on May 29, 2015 at 12:09am PDT + Live footage!!! Toscana apartments in Irvine A video posted by TT ð (@teyent_theequeenb) on May 29, 2015 at 12:09am PDT @@ -22,7 +22,7 @@ public function test_embed_reversal() { $expected_content = <<
Live footage!!! Toscana apartments in Irvine
A video posted by TT ð (@teyent_theequeenb) on May 29, 2015 at 12:09am PDT
Live footage!!! Toscana apartments in Irvine A video posted by TT ð (@teyent_theequeenb) on May 29, 2015 at 12:09am PDT