WordPress.org

Make WordPress Core


Ignore:
Timestamp:
09/30/2017 01:14:34 AM (3 years ago)
Author:
westonruter
Message:

Embeds: Cache oEmbeds in an oembed_cache custom post type instead of postmeta when there is no global $post.

Add processing of embeds to rich Text widget.

Props swissspidy, westonruter, ocean90, johnbillion.
See #40854, #39994, #40935.
Fixes #34115.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/wp-includes/class-wp-embed.php

    r41162 r41651  
    3131        // Hack to get the [embed] shortcode to run before wpautop()
    3232        add_filter( 'the_content', array( $this, 'run_shortcode' ), 8 );
     33        add_filter( 'widget_text_content', array( $this, 'run_shortcode' ), 8 );
    3334
    3435        // Shortcode placeholder for strip_shortcodes()
     
    3738        // Attempts to embed all URLs in a post
    3839        add_filter( 'the_content', array( $this, 'autoembed' ), 8 );
     40        add_filter( 'widget_text_content', array( $this, 'autoembed' ), 8 );
    3941
    4042        // After a post is saved, cache oEmbed items via Ajax
     
    186188
    187189        $post_ID = ( ! empty( $post->ID ) ) ? $post->ID : null;
    188         if ( ! empty( $this->post_ID ) ) // Potentially set by WP_Embed::cache_oembed()
     190
     191        // Potentially set by WP_Embed::cache_oembed().
     192        if ( ! empty( $this->post_ID ) ) {
    189193            $post_ID = $this->post_ID;
    190 
    191         // Unknown URL format. Let oEmbed have a go.
     194        }
     195
     196        // Check for a cached result (stored as custom post or in the post meta).
     197        $key_suffix    = md5( $url . serialize( $attr ) );
     198        $cachekey      = '_oembed_' . $key_suffix;
     199        $cachekey_time = '_oembed_time_' . $key_suffix;
     200
     201        /**
     202         * Filters the oEmbed TTL value (time to live).
     203         *
     204         * @since 4.0.0
     205         *
     206         * @param int    $time    Time to live (in seconds).
     207         * @param string $url     The attempted embed URL.
     208         * @param array  $attr    An array of shortcode attributes.
     209         * @param int    $post_ID Post ID.
     210         */
     211        $ttl = apply_filters( 'oembed_ttl', DAY_IN_SECONDS, $url, $attr, $post_ID );
     212
     213        $cache      = '';
     214        $cache_time = 0;
     215
     216        $cached_post_id = $this->find_oembed_post_id( $key_suffix );
     217
    192218        if ( $post_ID ) {
    193 
    194             // Check for a cached result (stored in the post meta)
    195             $key_suffix = md5( $url . serialize( $attr ) );
    196             $cachekey = '_oembed_' . $key_suffix;
    197             $cachekey_time = '_oembed_time_' . $key_suffix;
    198 
    199             /**
    200              * Filters the oEmbed TTL value (time to live).
    201              *
    202              * @since 4.0.0
    203              *
    204              * @param int    $time    Time to live (in seconds).
    205              * @param string $url     The attempted embed URL.
    206              * @param array  $attr    An array of shortcode attributes.
    207              * @param int    $post_ID Post ID.
    208              */
    209             $ttl = apply_filters( 'oembed_ttl', DAY_IN_SECONDS, $url, $attr, $post_ID );
    210 
    211219            $cache = get_post_meta( $post_ID, $cachekey, true );
    212220            $cache_time = get_post_meta( $post_ID, $cachekey_time, true );
     
    215223                $cache_time = 0;
    216224            }
    217 
    218             $cached_recently = ( time() - $cache_time ) < $ttl;
    219 
    220             if ( $this->usecache || $cached_recently ) {
    221                 // Failures are cached. Serve one if we're using the cache.
    222                 if ( '{{unknown}}' === $cache )
    223                     return $this->maybe_make_link( $url );
    224 
    225                 if ( ! empty( $cache ) ) {
    226                     /**
    227                      * Filters the cached oEmbed HTML.
    228                      *
    229                      * @since 2.9.0
    230                      *
    231                      * @see WP_Embed::shortcode()
    232                      *
    233                      * @param mixed  $cache   The cached HTML result, stored in post meta.
    234                      * @param string $url     The attempted embed URL.
    235                      * @param array  $attr    An array of shortcode attributes.
    236                      * @param int    $post_ID Post ID.
    237                      */
    238                     return apply_filters( 'embed_oembed_html', $cache, $url, $attr, $post_ID );
    239                 }
    240             }
    241 
    242             /**
    243              * Filters whether to inspect the given URL for discoverable link tags.
    244              *
    245              * @since 2.9.0
    246              * @since 4.4.0 The default value changed to true.
    247              *
    248              * @see WP_oEmbed::discover()
    249              *
    250              * @param bool $enable Whether to enable `<link>` tag discovery. Default true.
    251              */
    252             $attr['discover'] = ( apply_filters( 'embed_oembed_discover', true ) );
    253 
    254             // Use oEmbed to get the HTML
    255             $html = wp_oembed_get( $url, $attr );
    256 
    257             // Maybe cache the result
     225        } elseif ( $cached_post_id ) {
     226            $cached_post = get_post( $cached_post_id );
     227
     228            $cache      = $cached_post->post_content;
     229            $cache_time = strtotime( $cached_post->post_modified_gmt );
     230        }
     231
     232        $cached_recently = ( time() - $cache_time ) < $ttl;
     233
     234        if ( $this->usecache || $cached_recently ) {
     235            // Failures are cached. Serve one if we're using the cache.
     236            if ( '{{unknown}}' === $cache ) {
     237                return $this->maybe_make_link( $url );
     238            }
     239
     240            if ( ! empty( $cache ) ) {
     241                /**
     242                 * Filters the cached oEmbed HTML.
     243                 *
     244                 * @since 2.9.0
     245                 *
     246                 * @see WP_Embed::shortcode()
     247                 *
     248                 * @param mixed  $cache   The cached HTML result, stored in post meta.
     249                 * @param string $url     The attempted embed URL.
     250                 * @param array  $attr    An array of shortcode attributes.
     251                 * @param int    $post_ID Post ID.
     252                 */
     253                return apply_filters( 'embed_oembed_html', $cache, $url, $attr, $post_ID );
     254            }
     255        }
     256
     257        /**
     258         * Filters whether to inspect the given URL for discoverable link tags.
     259         *
     260         * @since 2.9.0
     261         * @since 4.4.0 The default value changed to true.
     262         *
     263         * @see WP_oEmbed::discover()
     264         *
     265         * @param bool $enable Whether to enable `<link>` tag discovery. Default true.
     266         */
     267        $attr['discover'] = apply_filters( 'embed_oembed_discover', true );
     268
     269        // Use oEmbed to get the HTML.
     270        $html = wp_oembed_get( $url, $attr );
     271
     272        if ( $post_ID ) {
    258273            if ( $html ) {
    259274                update_post_meta( $post_ID, $cachekey, $html );
     
    262277                update_post_meta( $post_ID, $cachekey, '{{unknown}}' );
    263278            }
    264 
    265             // If there was a result, return it
    266             if ( $html ) {
    267                 /** This filter is documented in wp-includes/class-wp-embed.php */
    268                 return apply_filters( 'embed_oembed_html', $html, $url, $attr, $post_ID );
    269             }
     279        } else {
     280            $has_kses = false !== has_filter( 'content_save_pre', 'wp_filter_post_kses' );
     281
     282            if ( $has_kses ) {
     283                // Prevent KSES from corrupting JSON in post_content.
     284                kses_remove_filters();
     285            }
     286
     287            wp_insert_post( wp_slash( array(
     288                'post_name'    => $key_suffix,
     289                'post_content' => $html ? $html : '{{unknown}}',
     290                'post_status'  => 'publish',
     291                'post_type'    => 'oembed_cache',
     292            ) ) );
     293
     294            if ( $has_kses ) {
     295                kses_init_filters();
     296            }
     297        }
     298
     299        // If there was a result, return it.
     300        if ( $html ) {
     301            /** This filter is documented in wp-includes/class-wp-embed.php */
     302            return apply_filters( 'embed_oembed_html', $html, $url, $attr, $post_ID );
    270303        }
    271304
     
    383416        return apply_filters( 'embed_maybe_make_link', $output, $url );
    384417    }
     418
     419    /**
     420     * Find the oEmbed cache post ID for a given cache key.
     421     *
     422     * @since 4.9.0
     423     *
     424     * @param string $cache_key oEmbed cache key.
     425     * @return int|null Post ID on success, null on failure.
     426     */
     427    public function find_oembed_post_id( $cache_key ) {
     428        $cache_group    = 'oembed_cache_post';
     429        $oembed_post_id = wp_cache_get( $cache_key, $cache_group );
     430
     431        if ( $oembed_post_id && 'oembed_cache' === get_post_type( $oembed_post_id ) ) {
     432            return $oembed_post_id;
     433        }
     434
     435        $oembed_post_query = new WP_Query( array(
     436            'post_type'              => 'oembed_cache',
     437            'post_status'            => 'publish',
     438            'name'                   => $cache_key,
     439            'posts_per_page'         => 1,
     440            'no_found_rows'          => true,
     441            'cache_results'          => true,
     442            'update_post_meta_cache' => false,
     443            'update_post_term_cache' => false,
     444            'lazy_load_term_meta'    => false,
     445        ) );
     446
     447        if ( ! empty( $oembed_post_query->posts ) ) {
     448            // Note: 'fields'=>'ids' is not being used in order to cache the post object as it will be needed.
     449            $oembed_post_id = $oembed_post_query->posts[0]->ID;
     450            wp_cache_set( $cache_key, $oembed_post_id, $cache_group );
     451
     452            return $oembed_post_id;
     453        }
     454
     455        return null;
     456    }
    385457}
Note: See TracChangeset for help on using the changeset viewer.