| 1 |
<?php |
| 2 |
/** |
| 3 |
* Docket Cache. |
| 4 |
* |
| 5 |
* @author Nawawi Jamili |
| 6 |
* @license MIT |
| 7 |
* |
| 8 |
* @see https://github.com/nawawi/docket-cache |
| 9 |
*/ |
| 10 |
|
| 11 |
namespace Nawawi\DocketCache; |
| 12 |
|
| 13 |
\defined('ABSPATH') || exit; |
| 14 |
|
| 15 |
final class MenuCache |
| 16 |
{ |
| 17 |
public function __construct() |
| 18 |
{ |
| 19 |
} |
| 20 |
|
| 21 |
public function register() |
| 22 |
{ |
| 23 |
if ($this->is_front_end()) { |
| 24 |
add_action('init', function () { |
| 25 |
add_filter('pre_wp_nav_menu', [$this, 'pre_wp_nav_menu'], \PHP_INT_MAX, 2); |
| 26 |
add_filter('wp_nav_menu', [$this, 'wp_nav_menu'], \PHP_INT_MAX, 2); |
| 27 |
}, \PHP_INT_MAX); |
| 28 |
} |
| 29 |
|
| 30 |
add_action('admin_init', function () { |
| 31 |
add_action('wp_update_nav_menu', [$this, 'wp_update_nav_menu'], \PHP_INT_MAX); |
| 32 |
add_action('wp_delete_nav_menu', [$this, 'wp_update_nav_menu'], \PHP_INT_MAX); |
| 33 |
add_filter('pre_set_theme_mod_nav_menu_locations', [$this, 'pre_set_theme_mod_nav_menu_locations'], \PHP_INT_MAX, 2); |
| 34 |
}, \PHP_INT_MAX); |
| 35 |
} |
| 36 |
|
| 37 |
private function is_front_end() |
| 38 |
{ |
| 39 |
if (!is_admin() |
| 40 |
&& (!\defined('WP_CLI') || !WP_CLI) |
| 41 |
&& (!\defined('DOING_AJAX') || !DOING_AJAX)) { |
| 42 |
return true; |
| 43 |
} |
| 44 |
|
| 45 |
if (!empty($_SERVER['REQUEST_URI']) && \function_exists('rest_get_url_prefix')) { |
| 46 |
$rest_prefix = rest_get_url_prefix(); |
| 47 |
|
| 48 |
return substr($_SERVER['REQUEST_URI'], 1, \strlen($rest_prefix)) === $rest_prefix; |
| 49 |
} |
| 50 |
|
| 51 |
return false; |
| 52 |
} |
| 53 |
|
| 54 |
private function normalize_menu_object(&$args) |
| 55 |
{ |
| 56 |
$menu = wp_get_nav_menu_object($args->menu); |
| 57 |
|
| 58 |
$locations = get_nav_menu_locations(); |
| 59 |
if (!$menu && $args->theme_location && $locations && isset($locations[$args->theme_location])) { |
| 60 |
$menu = wp_get_nav_menu_object($locations[$args->theme_location]); |
| 61 |
} |
| 62 |
|
| 63 |
if (!$menu && !$args->theme_location) { |
| 64 |
$menus = wp_get_nav_menus(); |
| 65 |
foreach ($menus as $menu_maybe) { |
| 66 |
$menu_items = wp_get_nav_menu_items($menu_maybe->term_id, ['update_post_term_cache' => false]); |
| 67 |
if ($menu_items) { |
| 68 |
$menu = $menu_maybe; |
| 69 |
break; |
| 70 |
} |
| 71 |
} |
| 72 |
} |
| 73 |
|
| 74 |
if (empty($args->menu) || is_numeric($args->menu)) { |
| 75 |
$args->menu = $menu; |
| 76 |
} |
| 77 |
} |
| 78 |
|
| 79 |
private function set_key($args) |
| 80 |
{ |
| 81 |
return md5(wp_json_encode($args)); |
| 82 |
} |
| 83 |
|
| 84 |
private function get_key($menu_key) |
| 85 |
{ |
| 86 |
return 'docketcache-menu-'.$menu_key; |
| 87 |
} |
| 88 |
|
| 89 |
private function get_cache($menu_key) |
| 90 |
{ |
| 91 |
return wp_cache_get($this->get_key($menu_key), 'docketcache-menu'); |
| 92 |
} |
| 93 |
|
| 94 |
private function navmenu_flush_cache() |
| 95 |
{ |
| 96 |
if (\function_exists('wp_cache_flush_group')) { |
| 97 |
wp_cache_flush_group('docketcache-menu'); |
| 98 |
} |
| 99 |
} |
| 100 |
|
| 101 |
public function pre_wp_nav_menu($output, $args) |
| 102 |
{ |
| 103 |
$this->normalize_menu_object($args); |
| 104 |
if (isset($args->menu->term_id)) { |
| 105 |
$menu_key = $this->set_key($args); |
| 106 |
if ($cached_output = $this->get_cache($menu_key)) { |
| 107 |
if (nwdcx_construe('SIGNATURE')) { |
| 108 |
$cached_output .= '<!-- This menu is cached by Docket Cache -->'.\PHP_EOL; |
| 109 |
} |
| 110 |
|
| 111 |
return $cached_output; |
| 112 |
} |
| 113 |
} |
| 114 |
|
| 115 |
return $output; |
| 116 |
} |
| 117 |
|
| 118 |
public function wp_nav_menu($nav_menu, $args) |
| 119 |
{ |
| 120 |
if (false !== strpos($nav_menu, 'no-cache')) { |
| 121 |
return $nav_menu; |
| 122 |
} |
| 123 |
|
| 124 |
if (isset($args->menu->term_id)) { |
| 125 |
$menu_key = $this->set_key($args); |
| 126 |
$cache_ttl = nwdcx_constval('MENUCACHE_TTL'); |
| 127 |
if (empty($cache_ttl) || !\is_int($cache_ttl)) { |
| 128 |
$cache_ttl = 1209600; // 14 days |
| 129 |
} |
| 130 |
|
| 131 |
wp_cache_set($this->get_key($menu_key), $nav_menu, 'docketcache-menu', $cache_ttl); |
| 132 |
} |
| 133 |
|
| 134 |
return $nav_menu; |
| 135 |
} |
| 136 |
|
| 137 |
public function wp_update_nav_menu($menu_id) |
| 138 |
{ |
| 139 |
$this->navmenu_flush_cache(); |
| 140 |
} |
| 141 |
|
| 142 |
public function pre_set_theme_mod_nav_menu_locations($new, $old) |
| 143 |
{ |
| 144 |
$this->navmenu_flush_cache(); |
| 145 |
|
| 146 |
return $new; |
| 147 |
} |
| 148 |
} |
| 149 |
|