Permalink
Browse files

Add object caching for the menu helper.

  • Loading branch information...
villesiltala committed Jan 25, 2019
1 parent 88f24de commit 9fe73d5342aea571f56813df98cc7f263ffdac59
Showing with 105 additions and 21 deletions.
  1. +11 −0 README.md
  2. +94 −21 helpers/menu.php
@@ -336,6 +336,17 @@ add_filter( "dustpress/cache/rendered", "__return_false" );

**Note!** When enabled, [DustPress Debugger](https://github.com/devgeniem/dustpress-debugger) turns both partial and end-result caching off.

### Menu caching

The menu helper uses [WP Object Cache](https://codex.wordpress.org/Class_Reference/WP_Object_Cache) to cache loaded menu items for each menu. The menu id (more specifically the term id of the menu) is used to build the cache key. No cache group is used. The menu helper also handles deleting the cache automatically when the menu is updated. To enable persistent caching you must install some third party plugin for it, for example [Redis Object Cache for WordPress](https://github.com/devgeniem/wp-redis-object-cache-dropin/).

#### Configuration constants

You can define the following PHP constants to control menu helper caching:

- `DUSTPRESS_MENU_HELPER_CACHE_EXPIRE : int`: The menu items cache expiration time in seconds. The default value used is 15 minutes (900) if the constant is not set.
- `DUSTPRESS_MENU_HELPER_CACHE_DISABLE : bool`: Set to `true` if you want to disable caching. The cache is enabled by default.

## Dust templates

DustPHP templates are 100% compatible with Dust.js templates. See the official [Dust.js website](http://www.dustjs.com/) for documentation or the [LinkedIn Dust Tutorial](https://github.com/linkedin/dustjs/wiki/Dust-Tutorial).
@@ -10,6 +10,11 @@
*/
class Menu extends Helper {
/**
* The object cache key prefix.
*/
const CACHE_KEY_PREFIX = 'dustpress_menu_helper_';
/**
* Renders and outputs the menu HTML.
*
@@ -146,7 +151,13 @@ public static function get_menu_data( $menu_name, $parent = 0, $override = null,
}
if ( isset( $menu_object) ) {
$menu_items = \wp_get_nav_menu_items( $menu_object );
$menu_items = static::get_cached_menu_items( $menu_object->term_id );
if ( empty( $menu_items ) ) {
$menu_items = \wp_get_nav_menu_items( $menu_object );
static::set_cached_menu_items( $menu_object->term_id, $menu_items );
}
// Add menu object location to the menu object.
// You can use this to filter specific menu items.
@@ -173,24 +184,24 @@ public static function get_menu_data( $menu_name, $parent = 0, $override = null,
if ( $menu_items ) {
$built_menu_items = self::build_menu( $menu_items, $parent_id, null, $override );
$built_menu_items = self::build_menu( $menu_items, $parent_id, null, $override );
$active = array_keys( $built_menu_items, 'active' );
$active = array_keys( $built_menu_items, 'active' );
foreach( $active as $index ) {
unset( $built_menu_items[ $index ] );
}
if ( 0 === array_search( 'active', $built_menu_items ) ) {
unset( $built_menu_items[0] );
}
foreach( $active as $index ) {
unset( $built_menu_items[ $index ] );
}
if ( 0 === array_search( 'active', $built_menu_items ) ) {
unset( $built_menu_items[0] );
}
// return menu object and menu items
$menu = [];
$menu['menu_object'] = apply_filters( 'dustpress/menu/object/location=' . $menu_object->location, $menu_object );
$menu['menu_items'] = apply_filters( 'dustpress/menu/items/location=' . $menu_object->location, $built_menu_items );
// return menu object and menu items
$menu = [];
$menu['menu_object'] = apply_filters( 'dustpress/menu/object/location=' . $menu_object->location, $menu_object );
$menu['menu_items'] = apply_filters( 'dustpress/menu/items/location=' . $menu_object->location, $built_menu_items );
return apply_filters( 'dustpress/menu', $menu );
return apply_filters( 'dustpress/menu', $menu );
}
}
@@ -216,7 +227,7 @@ private static function build_menu( $menu_items, $parent = 0, $type = 'page', $o
}
if ( count( $menu_items ) > 0 ) {
foreach ( $menu_items as $item ) {
foreach ( $menu_items as $item ) {
if ( $item->menu_item_parent == $parent ) {
$item->sub_menu = self::build_menu( $menu_items, $item->ID, $item->object, $override );
@@ -272,18 +283,80 @@ private static function is_current( $item, $override ) {
$term_id = \get_queried_object()->term_id;
$return = ( $item->object_id == $term_id && 'taxonomy' == $item->type )
|| ( $item->object_id == $override );
|| ( $item->object_id == $override );
}
else {
$return = ( \get_the_ID() == $item->object_id
&& 'post_type' == $item->type )
// Check if on a static page that shows posts.
|| ( \is_home() && ! \is_front_page() && \get_queried_object_id() == $item->object_id )
|| ( $item->object_id == $override );
&& 'post_type' == $item->type )
// Check if on a static page that shows posts.
|| ( \is_home() && ! \is_front_page() && \get_queried_object_id() == $item->object_id )
|| ( $item->object_id == $override );
}
return apply_filters( "dustpress/menu/is_current", $return, $item );
}
/**
* Get the cached menu items.
*
* @param mixed $menu_id The menu id.
*
* @return bool|array
*/
protected static function get_cached_menu_items( int $menu_id ) {
if ( static::disable_cache() ) {
return false;
}
$cache = wp_cache_get( static::CACHE_KEY_PREFIX . $menu_id );
return $cache;
}
/**
* Set menu items into cache.
*
* @param mixed $menu_id The menu id.
* @param array $menu_items The menu items.
*
* @return bool
*/
protected static function set_cached_menu_items( int $menu_id, $menu_items ) {
if ( static::disable_cache() ) {
return false;
}
// Define the cache expiration time in secods.
$expire = defined( 'DUSTPRESS_MENU_HELPER_CACHE_EXPIRE' ) ? DUSTPRESS_MENU_HELPER_CACHE_EXPIRE : 15 * MINUTE_IN_SECONDS;
return wp_cache_set( static::CACHE_KEY_PREFIX . $menu_id, $menu_items, null, $expire );
}
/**
* Delete menu items cache when a menu is updated.
*
* @param int $menu_id The menu id.
*
* @return bool
*/
public static function delete_cache_menu_items( $menu_id = 0 ) {
if ( static::disable_cache() ) {
return false;
}
return wp_cache_delete( static::CACHE_KEY_PREFIX . $menu_id );
}
/**
* Defines whether to disable caching.
*
* @return bool
*/
protected static function disable_cache() {
$disable = defined( 'DUSTPRESS_MENU_HELPER_CACHE_DISABLE' ) && DUSTPRESS_MENU_HELPER_CACHE_DISABLE === true;
return $disable;
}
}
$this->add_helper( 'menu', new Menu() );
// Add hook to delete menu items cache if a menu is updated.
add_action( 'wp_update_nav_menu', [ Menu::class, 'delete_cache_menu_items' ], 1, 1 );

0 comments on commit 9fe73d5

Please sign in to comment.