Skip to content

Instantly share code, notes, and snippets.

@petenelson
Created February 3, 2017 19:19
Show Gist options
  • Save petenelson/30e901fc387173fc5eea8a5031494bc1 to your computer and use it in GitHub Desktop.
Save petenelson/30e901fc387173fc5eea8a5031494bc1 to your computer and use it in GitHub Desktop.
WordPress: Cached navigation menu helper function
<?php
/**
* Helper functions for caching WordPress navigation menu HTML.
*/
namespace PeteNelson\Navigation;
add_action( 'init', __NAMESPACE__ . '\setup' );
/**
* Sets up WordPress hooks and filters.
*
* @return void
*/
function setup() {
// All of the actions used to invalidate the menu cache.
$invalidate_actions = array(
'wp_add_nav_menu_item',
'wp_update_nav_menu_item',
'wp_create_nav_menu',
'wp_update_nav_menu',
'wp_delete_nav_menu',
);
foreach( $invalidate_actions as $action ) {
add_action( $action, __NAMESPACE__ . '\invalidate_menu_caches' );
}
}
/**
* Echoes a cached wp_nav_menu() call.
*
* @param array $nav_menu_args wp_nav_menu() args.
* @return void
*/
function cached_wp_nav_menu( $nav_menu_args ) {
$nav_menu_args = wp_parse_args( $nav_menu_args, array(
'echo' => true,
)
);
$walker_class = '';
// See if the walker is an object.
if ( isset( $nav_menu_args['walker'] ) && ! empty( $nav_menu_args['walker'] && is_object( $nav_menu_args['walker'] ) ) ) {
$walker_class = get_class( $nav_menu_args['walker'] );
}
// Build a cache key using the args, walker class, and current
// incremenetor value;
$key = '_cached_menu_html_' . md5( json_encode( $nav_menu_args ) . $walker_class ) . '_' . get_incrementor();
// See if we have the menu HTML cached.
$menu_html = wp_cache_get( $key );
if ( false !== $menu_html ) {
echo $menu_html;
return;
}
// We don't have it cached, get the HTML, either captured or returned.
if ( $nav_menu_args['echo'] ) {
ob_start();
wp_nav_menu( $nav_menu_args );
$menu_html = ob_get_clean();
} else {
$menu_html = wp_nav_menu( $nav_menu_args );
}
// Get random cache time.
$cache_time = mt_rand( 45 * MINUTE_IN_SECONDS, 60 * MINUTE_IN_SECONDS );
// Cache the menu HTML.
wp_cache_set( $key, $menu_html, '', $cache_time );
echo $menu_html;
}
/**
* Returns the cache key used for the incrementor.
*
* @return string
*/
function get_incrementor_cache_key() {
return '_cached_menu_html_incr';
}
/**
* Gets the current incrementor value, can also incremenent it.
*
* @param boolean $increment Incremenet the value?
* @return int
*/
function get_incrementor( $increment = false ) {
// Get the incrementor cache key.
$key = get_incrementor_cache_key();
// Set it if it doesn't exist.
$incr_value = wp_cache_get( $key );
if ( empty( $incr_value ) ) {
$incr_value = 1;
wp_cache_set( $key, $incr_value );
}
// Do we need to increment it?
if ( $increment ) {
$incr_value = wp_cache_incr( $key );
}
return $incr_value;
}
/**
* Invalidates all cached menus.
*
* @return void
*/
function invalidate_menu_caches() {
// Just need to update the incrementor.
get_incrementor( true );
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment