If you saw my last post, you may have noticed some cool embeds. These are coming from the Embed Extended plugin. This plugin takes OpenGraph data and treats it more like oEmbed data for WordPress. It works great with the block editor as well!
Tag: oembed
-

Wisps, a WordPress Plugin
Last year I had a need for an editable JSON file that was retrievable via HTTP. Of course there’s a million ways that I could do this, but the easiest I thought of would be to have it inside of WordPress, since all of the people that needed access to edit the file already had edit access to a specific site. So I built a plugin.
Doing this inside WordPress already brings a lot of benefits with little to no effort:
- User Management
- Revision History
- oEmbed Support
- Permalinks
- Syntax Highlighting Code Editor
- Self-Hosted Data
Possibly more benefits as well, depending on the setup, such as caching.
I’ve tweaked the plugin some, and I’m almost ready to submit it to the WordPress.org Plugin Repository. I just need to do the hard part of figuring out artwork. Ugh.
Introducing Wisps:
Wisps are embeddable and sharable code snippets for WordPress.
With Wisps, you can have code snippets similar to Gist, Pastebin, or similar code sharing sites. Using the built-in WordPress code editor, you can write snippets to post and share. This has the benefit of WordPress revisions, auto-drafts, etc to keep a record of how code changes.
Wisps can be downloaded by appending
/download/to the permalink, or viewed raw by adding/view/or/raw/. There is full oEmbed support so you can just paste in a link to a wisp in the editor and it will be fully embedded.PrismJS is used for syntax highlighting for oEmbeds.
You can add Wisp support to your theme either by modifying the custom post type
page-wisp.phptemplate, which will continue to display Wisps in the loop securely, or you can useadd_theme_support( 'wisps' )to tell the plugin to not automatically escape the output. You can then do what you like, such as potentially adding frontend support for syntax highlighting.Here’s what the oEmbed data looks like:
(Yeah, I totally stole the design from Gists, because I’m not talented 😬)
Currently available on GitHub
Wisps are Gist-like code posts for WordPress
https://github.com/emrikol/Wisps
0 forks.
2 stars.
0 open issues.
Recent commits:
- Merge pull request #2 from emrikol/dev2.0?, GitHub
- Update class-wisps.php, Derrick Tennant
- Translations, etc., Derrick Tennant
- Create readme.txt, Derrick Tennant
- Bring all assets in to assets dir, Derrick Tennant
Hopefully one day available on the WordPress.org Plugin Repository 🙂
If you give it a try and have any suggestions, or issues drop me a line here or on GitHub!
-

Query Caching (and a little extra)
By default, WordPress does not cache
WP_Queryqueries. Doing so can greatly improve performance. The way I do this is via the Advanced Post Cache plugin:All up in your WP_Query, caching the things.
https://github.com/Automattic/advanced-post-cache
17 forks.
62 stars.
14 open issues.
Recent commits:
- Update README with deprecation notice and archive info, GitHub
- Merge pull request #32 from Automattic/no-op-pass-twoAdd better readme and be explicit in plugin header and composer.json to indicate the plugin is deprecated., GitHub
- Add better readme and be explicit in plugin header and composer.json to indicate the plugin is deprecated., Rinat Khaziev
- Merge pull request #31 from Automattic/no-opNo-op the plugin, it's obsolete, GitHub
- No-op the plugin, it's obsolete, Rinat Khaziev
By running this plugin (hopefully as an
mu-plugin) with a persistent object cache,WP_Querycalls, along withget_post()calls (only ifsuppress_filtersisfalse) will be cached.Bonus!
Now that we’re caching queries, here’s how I do a little extra caching to squeeze out a tiny bit more performance:
<?php // By default Jetpack does not cache responses from Instagram oembeds. add_filter( 'instagram_cache_oembed_api_response_body', '__return_true' ); // Cache WP Dashboard Recent Posts Query add_filter( 'dashboard_recent_posts_query_args', 'cache_dashboard_recent_posts_query_args', 10, 1 ); function cache_dashboard_recent_posts_query_args( $query_args ) { $query_args['cache_results'] = true; $query_args['suppress_filters'] = false; return $query_args; } // Cache WP Dashboard Recent Drafts Query add_filter( 'dashboard_recent_drafts_query_args', 'cache_dashboard_recent_drafts_query_args', 10, 1 ); function cache_dashboard_recent_drafts_query_args( $query_args ) { $query_args['suppress_filters'] = false; return $query_args; } // Cache comment counts, https://github.com/Automattic/vip-code-performance/blob/master/core-fix-comment-counts-caching.php add_filter( 'wp_count_comments', 'wpcom_vip_cache_full_comment_counts', 10, 2 ); function wpcom_vip_cache_full_comment_counts( $counts = false , $post_id = 0 ){ //We are only caching the global comment counts for now since those are often in the millions while the per page one is usually more reasonable. if ( 0 !== $post_id ) { return $counts; } $cache_key = "vip-comments-{$post_id}"; $stats_object = wp_cache_get( $cache_key ); //retrieve comments in the same way wp_count_comments() does if ( false === $stats_object ) { $stats = get_comment_count( $post_id ); $stats['moderated'] = $stats['awaiting_moderation']; unset( $stats['awaiting_moderation'] ); $stats_object = (object) $stats; wp_cache_set( $cache_key, $stats_object, 'default', 30 * MINUTE_IN_SECONDS ); } return $stats_object; } // Cache monthly media array. add_filter( 'media_library_months_with_files', 'wpcom_vip_media_library_months_with_files' ); function wpcom_vip_media_library_months_with_files() { $months = wp_cache_get( 'media_library_months_with_files', 'extra-caching' ); if ( false === $months ) { global $wpdb; $months = $wpdb->get_results( $wpdb->prepare( " SELECT DISTINCT YEAR( post_date ) AS year, MONTH( post_date ) AS month FROM $wpdb->posts WHERE post_type = %s ORDER BY post_date DESC ", 'attachment' ) ); wp_cache_set( 'media_library_months_with_files', $months, 'extra-caching' ); } return $months; } add_action( 'add_attachment', 'media_library_months_with_files_bust_cache' ); function media_library_months_with_files_bust_cache( $post_id ) { if ( defined( 'WP_IMPORTING' ) && WP_IMPORTING ) { return; } // What month/year is the most recent attachment? global $wpdb; $months = $wpdb->get_results( $wpdb->prepare( " SELECT DISTINCT YEAR( post_date ) AS year, MONTH( post_date ) AS month FROM $wpdb->posts WHERE post_type = %s ORDER BY post_date DESC LIMIT 1 ", 'attachment' ) ); // Simplify by assigning the object to $months $months = array_shift( array_values( $months ) ); // Compare the dates of the new, and most recent, attachment if ( ! $months->year == get_the_time( 'Y', $post_id ) && ! $months->month == get_the_time( 'm', $post_id ) ) { // the new attachment is not in the same month/year as the // most recent attachment, so we need to refresh the transient wp_cache_delete( 'media_library_months_with_files', 'extra-caching' ); } }Code language: HTML, XML (xml)
