My favorites | Sign in
Project Home Downloads Wiki Issues Source
Checkout   Browse   Changes    
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
<?php

/**
* This implements a WordPress text filter to handle output of the wp_nav_menu
* function (also used by the "Custom Menu" widget). Submenu ULs that don't have
* the active menu item are removed, so the user has to drill down into the
* submenus.
*
* Under the hood, DOMDocument/DOMXPath are used, so it requires the libxml
* PHP extension: http://www.php.net/manual/en/dom.requirements.php
*
* <code>
* // in functions.php
* Coewp_MenuFilter::add();
* </code>
*
* @author Steve Clay <steve@mrclay.org>
* @license http://www.opensource.org/licenses/mit-license.php MIT License
*/
class Coewp_MenuFilter {

/**
* Add this filter to WordPress's wp_nav_menu hook
*/
public static function add()
{
add_filter('wp_nav_menu', array('Coewp_MenuFilter', 'staticFilter'));
}

/**
* Filter menu removing submenus in inactive branches. This static version
* allows immediate disposal of the object after filtering
*
* @param $html
* @return string
*/
public static function staticFilter($html)
{
$filter = new self;
return $filter->filter($html);
}

/**
* Filter menu removing submenus in inactive branches
*
* @param $html
* @return string
*/
public function filter($html)
{
$doc = new DOMDocument();

// supress loadHTML warnings http://www.php.net/manual/en/domdocument.loadhtml.php#95463
libxml_use_internal_errors(true);

if (! @$doc->loadHTML("<html><body>" . $html . '</body></html>')) {
return $html;
}
$this->_xpath = new DOMXPath($doc);
$menu = $this->_xpath->query('//ul[1]');
if ($menu->length) {
// recursively walk menu ULs
$this->_handleUl($menu->item(0));
}

$html = $doc->saveHTML();
list(,$html) = explode('<body>', $html, 2);
list($html) = explode('</body>', $html, 2);

return $html;
}

/**
* Check all child LIs, and remove their submenus if they don't contain
* an LI with class "current-menu-item". If it is the current branch,
* call this function recursively on the submenu UL.
*
* @param DOMElement $ul
*/
protected function _handleUl(DOMElement $ul)
{
foreach ($this->_xpath->query('./li', $ul) as $li) {
$childUl = $this->_xpath->query('./ul', $li);
if ($childUl->length) {
$isActiveBranch = false;
foreach ($this->_xpath->query('. | .//li', $li) as $descLi) {
if (preg_match('@(^| )current-menu-item( |$)@', $descLi->getAttribute('class'))) {
$isActiveBranch = true;
break;
}
}
if ($isActiveBranch) {
$this->_handleUl($childUl->item(0));
} else {
$li->removeChild($childUl->item(0));
}
}
}
}

/**
* @var DOMXPath
*/
protected $_xpath = null;
}

Change log

r83 by mrclay.org on Feb 28, 2012   Diff
Add license. Some needed cleanup
Go to: 
Project members, sign in to write a code review

Older revisions

r38 by st...@mrclay.org on Feb 1, 2011   Diff
whitespace cleanup
r37 by st...@mrclay.org on Feb 1, 2011   Diff
+ WP menu filter
All revisions of this file

File info

Size: 3080 bytes, 105 lines
Powered by Google Project Hosting