Custom Menu Wizard Widget - Version 3.0.3

Version Description

  • bugfix : removed all occurrences of "Plugin " followed by "Name" from everywhere except the main plugin file to avoid update() reporting Invalid Header when activating straight from installation (rather than from the Plugins page)
  • tweak : eliminate the over-use of get_title() when determining the widget title
  • tweak : added self-terminating forward slash to generated shortcodes
  • change : prepare for WordPress v4 (avoid use of deprecated functions)
Download this release

Release Info

Developer wizzud
Plugin Icon 128x128 Custom Menu Wizard Widget
Version 3.0.3
Comparing to
See all releases

Code changes from version 3.0.2 to 3.0.3

custom-menu-wizard.js CHANGED
@@ -1,4 +1,4 @@
1
- /* Plugin Name: Custom Menu Wizard
2
  * Script for controlling this widget's options (in Admin -> Widgets)
3
  */
4
  /*global jQuery, window, document, ajaxurl */
@@ -859,7 +859,7 @@ jQuery(function($){
859
  v.push( $.isArray(args[n]) ? n + '="' + args[n].join(',') + '"' : n + '=' + args[n] );
860
  }
861
  //NB at v3.0.0, the shortcode changed from custom_menu_wizard to cmwizard (the previous version is still supported)
862
- return '[cmwizard ' + v.join(' ') + ']';
863
  }, //end cmwAssist.shortcode()
864
  /**
865
  * updates the graphic menu structure from the widget data
1
+ /* Custom Menu Wizard plugin
2
  * Script for controlling this widget's options (in Admin -> Widgets)
3
  */
4
  /*global jQuery, window, document, ajaxurl */
859
  v.push( $.isArray(args[n]) ? n + '="' + args[n].join(',') + '"' : n + '=' + args[n] );
860
  }
861
  //NB at v3.0.0, the shortcode changed from custom_menu_wizard to cmwizard (the previous version is still supported)
862
+ return '[cmwizard ' + v.join(' ') + '/]';
863
  }, //end cmwAssist.shortcode()
864
  /**
865
  * updates the graphic menu structure from the widget data
custom-menu-wizard.min.js CHANGED
@@ -1,10 +1,10 @@
1
  /*Source: custom-menu-wizard.js
2
- *Compiled: 2014-06-13, Google Closure Compiler...
3
  *STATISTICS
4
- * - originalSize: 61388
5
  * - originalGzipSize: 15232
6
- * - compressedSize: 22367
7
- * - compressedGzipSize: 7096
8
  */
9
  jQuery(function(f){var z,y=function(a,b){return(b?".":"")+"widget-custom-menu-wizard-"+a},D=function(a){var b=f(this).data().cmwDialogVersion.replace(/\./g,""),b=/^\d+$/.test(b)?"v"+b:b;z[b]?z[b].update(a?a.target:this):z.update(a?a.target:this)},E=function(a,b,d){var c="tick"===d?b._items_sep:b._exclude_sep,g=[],l="tick"===d?"_items":"_exclude",l=b[l]?f.grep(b[l].split(c),function(b){return/\+$/.test(b)?(g.push(parseInt(b,10)),!b):!!b}):[],l=c+l.join(c)+c,g=c+g.join(c)+c;a=a.each(function(){var b=
10
  f(this),a=b.data(),s=-1<g.indexOf(c+a.itemid+c),a=s||-1<l.indexOf(c+a.itemid+c);b.toggleClass("cmw-has-"+d,a).toggleClass("cmw-inherit-"+d,s)});return a.filter(".cmw-inherit-"+d).find("li").removeClass("cmw-has-"+d+" cmw-inherit-"+d).add(a.filter(".cmw-has-"+d))},B=function(a,b){return(a?a:b)[a?"find":"closest"](y("onchange",1))},H=function(a){var b={},d="2.1.0"===a.data("cmwDialogVersion"),c={items:1,exclude:1},g=f.extend({branch_start:1,exclude_level:1},c);f.each(a.find(":input").serializeArray(),
@@ -29,7 +29,7 @@ a.find(".cmw-depth,.cmw-fallback-depth").each(function(){var a=f(this),c=a.find(
29
  "not-fb-pc":!{parent:1,current:1}[b.find(".cmw-fallback").val()]},function(a,c){b.find(".cmw-disableif"+a).toggleClass("cmw-colour-grey",c).find("input,select").prop("disabled",c)})},shortcode:function(a){var b={menu:a.menu},d="branch"===a.filter,c="items"===a.filter,g;a.title&&!a.hide_title&&(b.title=[a.title]);!d&&!c&&1<a.level&&(b.level=a.level);d&&(b.branch=a.branch||"current",a.branch_start&&(b.start_at=[a.branch_start]),"level"===a.start_mode&&(b.start_mode="level"));c&&(b.items=[a._items]);
30
  0<a.depth&&(b.depth=a.depth);a.depth_rel_current&&0<a.depth&&(b.depth_rel_current=1);d&&!a.branch&&a.fallback&&(b.fallback=[a.fallback],"quit"!==a.fallback&&(a.fallback_siblings&&b.fallback.push("+siblings"),a.fallback_depth&&b.fallback.push(a.fallback_depth)));d&&a.ancestors&&(b.ancestors=a.ancestors,a.ancestor_siblings&&(b.ancestor_siblings=a.ancestor_siblings));a._exclude&&(b.exclude=[a._exclude]);a.exclude_level&&(b.exclude_level=[a.exclude_level]);c=[];a.title_from_current?c.push("current"):
31
  a.title_from_current_root&&c.push("current-root");d&&a.title_from_branch?c.push("branch"):d&&a.title_from_branch_root&&c.push("branch-root");c.length&&(b.title_from=c);for(c in{allow_all_root:1,siblings:1,include_root:1,flat_output:1,ol_root:1,ol_sub:1})a[c]&&(b[c]=1);d={contains_current:"",container:"div",container_id:"",container_class:"",menu_class:"menu-widget",widget_class:""};for(c in d)a[c]!==d[c]&&(b[c]=[a[c]]);d={wrap_link:"before",wrap_link_text:"link_before"};for(c in d)(g=a[d[c]].toString().match(/^<(\w+)/))&&
32
- g[1]&&(b[c]=[g[1]]);d=[];for(c in b)d.push(f.isArray(b[c])?c+'="'+b[c].join(",")+'"':c+"="+b[c]);return"[cmwizard "+d.join(" ")+"]"},update:function(a){var b=f(a);a=B(0,b);var d=f("#"+a.data().cmwDialogId),c=-1,g=9999,l=0,e=0,k="",s,u,r,v,x,m,t,h,y,A,z,w,C,q,p,n;b.hasClass("cmw-listen")&&this.setFields(b,a);m=H(a);if(d.length&&d.dialog("isOpen")){d.dialog("moveToTop");b.hasClass("cmw-select-menu")&&G(d);b="branch"===m.filter;u="items"===m.filter;s=!b&&!u;v=b&&!m.branch;t=d.find(".cmw-demo-themenu-ul");
33
  x=t.data().maxLevel;w=t.find(".current-menu-item").closest("li");C=w.length?w.data().level:-1;h=t.find("li").removeData("included").removeClass("title-from-item");A=m.depth;z=m.depth_rel_current;y=E(h,m,"cross");u&&(h=E(h,m,"tick"));h.length&&!w.length&&(m.contains_current||v)&&(h=f([]));b&&h.length&&(q=v?w:h.filter("[data-itemid="+m.branch+"]"),q.length?(c=q.data().level||0,h=q.add(q.find("li")),r=q):h=f([]));if(s&&h.length&&1<m.level){p=1;for(n=[];p<m.level;p++)n.push(".level-"+p);h=h.not(n.join(","))}"primary"===
34
  m.contains_current&&h.length&&!w.is(h)&&(h=f([]));if(s&&h.length&&A&&(p=z&&C>=m.level?C:m.level,p+=A,p<=x)){for(n=[];p<=x;p++)n.push(".level-"+p);h=h.not(n.join(","))}if(b&&h.length&&(n=parseInt(m.branch_start,10),n=isNaN(n)||!n?c:m.branch_start.match(/^(\+|-)/)?Math.max(1,c+n):n,v&&m.fallback&&!w.find("li").length&&(k="cmw-fellback-to-"+m.fallback,"quit"===m.fallback?n=x+1:(n="current"===m.fallback||2>c?c:c-1,m.fallback_depth&&(A=m.fallback_depth,z=1))),n>x?h=f([]):(n<c&&(q=q.parentsUntil(t,"li.level-"+
35
  n)),"level"===m.start_mode&&n<=c&&(1<n||m.allow_all_root)?h=q.parent().find("li"):n<c&&(h=q.add(q.find("li"))),k&&m.fallback_siblings&&h.length&&(1<n||m.allow_all_root)&&(h=h.add(q.siblings("li.level-"+n)))),h.length)){c=n;q=9999;A&&(q=z&&C>=c&&h.filter(w).length?C:c,q+=A,g=q-1);p=1;for(n=[];p<=x;p++)p>=c&&p<q&&n.push(".level-"+p);h=h.filter(n.join(","))}"secondary"===m.contains_current&&h.length&&!w.is(h)&&(h=f([]));if(b&&h.length){n=r.data().level;if(m.ancestors&&(r.is(h)||n>g)){p=m.ancestors;0>
1
  /*Source: custom-menu-wizard.js
2
+ *Compiled: 2014-07-24, Google Closure Compiler...
3
  *STATISTICS
4
+ * - originalSize: 61383
5
  * - originalGzipSize: 15232
6
+ * - compressedSize: 22368
7
+ * - compressedGzipSize: 7100
8
  */
9
  jQuery(function(f){var z,y=function(a,b){return(b?".":"")+"widget-custom-menu-wizard-"+a},D=function(a){var b=f(this).data().cmwDialogVersion.replace(/\./g,""),b=/^\d+$/.test(b)?"v"+b:b;z[b]?z[b].update(a?a.target:this):z.update(a?a.target:this)},E=function(a,b,d){var c="tick"===d?b._items_sep:b._exclude_sep,g=[],l="tick"===d?"_items":"_exclude",l=b[l]?f.grep(b[l].split(c),function(b){return/\+$/.test(b)?(g.push(parseInt(b,10)),!b):!!b}):[],l=c+l.join(c)+c,g=c+g.join(c)+c;a=a.each(function(){var b=
10
  f(this),a=b.data(),s=-1<g.indexOf(c+a.itemid+c),a=s||-1<l.indexOf(c+a.itemid+c);b.toggleClass("cmw-has-"+d,a).toggleClass("cmw-inherit-"+d,s)});return a.filter(".cmw-inherit-"+d).find("li").removeClass("cmw-has-"+d+" cmw-inherit-"+d).add(a.filter(".cmw-has-"+d))},B=function(a,b){return(a?a:b)[a?"find":"closest"](y("onchange",1))},H=function(a){var b={},d="2.1.0"===a.data("cmwDialogVersion"),c={items:1,exclude:1},g=f.extend({branch_start:1,exclude_level:1},c);f.each(a.find(":input").serializeArray(),
29
  "not-fb-pc":!{parent:1,current:1}[b.find(".cmw-fallback").val()]},function(a,c){b.find(".cmw-disableif"+a).toggleClass("cmw-colour-grey",c).find("input,select").prop("disabled",c)})},shortcode:function(a){var b={menu:a.menu},d="branch"===a.filter,c="items"===a.filter,g;a.title&&!a.hide_title&&(b.title=[a.title]);!d&&!c&&1<a.level&&(b.level=a.level);d&&(b.branch=a.branch||"current",a.branch_start&&(b.start_at=[a.branch_start]),"level"===a.start_mode&&(b.start_mode="level"));c&&(b.items=[a._items]);
30
  0<a.depth&&(b.depth=a.depth);a.depth_rel_current&&0<a.depth&&(b.depth_rel_current=1);d&&!a.branch&&a.fallback&&(b.fallback=[a.fallback],"quit"!==a.fallback&&(a.fallback_siblings&&b.fallback.push("+siblings"),a.fallback_depth&&b.fallback.push(a.fallback_depth)));d&&a.ancestors&&(b.ancestors=a.ancestors,a.ancestor_siblings&&(b.ancestor_siblings=a.ancestor_siblings));a._exclude&&(b.exclude=[a._exclude]);a.exclude_level&&(b.exclude_level=[a.exclude_level]);c=[];a.title_from_current?c.push("current"):
31
  a.title_from_current_root&&c.push("current-root");d&&a.title_from_branch?c.push("branch"):d&&a.title_from_branch_root&&c.push("branch-root");c.length&&(b.title_from=c);for(c in{allow_all_root:1,siblings:1,include_root:1,flat_output:1,ol_root:1,ol_sub:1})a[c]&&(b[c]=1);d={contains_current:"",container:"div",container_id:"",container_class:"",menu_class:"menu-widget",widget_class:""};for(c in d)a[c]!==d[c]&&(b[c]=[a[c]]);d={wrap_link:"before",wrap_link_text:"link_before"};for(c in d)(g=a[d[c]].toString().match(/^<(\w+)/))&&
32
+ g[1]&&(b[c]=[g[1]]);d=[];for(c in b)d.push(f.isArray(b[c])?c+'="'+b[c].join(",")+'"':c+"="+b[c]);return"[cmwizard "+d.join(" ")+"/]"},update:function(a){var b=f(a);a=B(0,b);var d=f("#"+a.data().cmwDialogId),c=-1,g=9999,l=0,e=0,k="",s,u,r,v,x,m,t,h,y,A,z,w,C,q,p,n;b.hasClass("cmw-listen")&&this.setFields(b,a);m=H(a);if(d.length&&d.dialog("isOpen")){d.dialog("moveToTop");b.hasClass("cmw-select-menu")&&G(d);b="branch"===m.filter;u="items"===m.filter;s=!b&&!u;v=b&&!m.branch;t=d.find(".cmw-demo-themenu-ul");
33
  x=t.data().maxLevel;w=t.find(".current-menu-item").closest("li");C=w.length?w.data().level:-1;h=t.find("li").removeData("included").removeClass("title-from-item");A=m.depth;z=m.depth_rel_current;y=E(h,m,"cross");u&&(h=E(h,m,"tick"));h.length&&!w.length&&(m.contains_current||v)&&(h=f([]));b&&h.length&&(q=v?w:h.filter("[data-itemid="+m.branch+"]"),q.length?(c=q.data().level||0,h=q.add(q.find("li")),r=q):h=f([]));if(s&&h.length&&1<m.level){p=1;for(n=[];p<m.level;p++)n.push(".level-"+p);h=h.not(n.join(","))}"primary"===
34
  m.contains_current&&h.length&&!w.is(h)&&(h=f([]));if(s&&h.length&&A&&(p=z&&C>=m.level?C:m.level,p+=A,p<=x)){for(n=[];p<=x;p++)n.push(".level-"+p);h=h.not(n.join(","))}if(b&&h.length&&(n=parseInt(m.branch_start,10),n=isNaN(n)||!n?c:m.branch_start.match(/^(\+|-)/)?Math.max(1,c+n):n,v&&m.fallback&&!w.find("li").length&&(k="cmw-fellback-to-"+m.fallback,"quit"===m.fallback?n=x+1:(n="current"===m.fallback||2>c?c:c-1,m.fallback_depth&&(A=m.fallback_depth,z=1))),n>x?h=f([]):(n<c&&(q=q.parentsUntil(t,"li.level-"+
35
  n)),"level"===m.start_mode&&n<=c&&(1<n||m.allow_all_root)?h=q.parent().find("li"):n<c&&(h=q.add(q.find("li"))),k&&m.fallback_siblings&&h.length&&(1<n||m.allow_all_root)&&(h=h.add(q.siblings("li.level-"+n)))),h.length)){c=n;q=9999;A&&(q=z&&C>=c&&h.filter(w).length?C:c,q+=A,g=q-1);p=1;for(n=[];p<=x;p++)p>=c&&p<q&&n.push(".level-"+p);h=h.filter(n.join(","))}"secondary"===m.contains_current&&h.length&&!w.is(h)&&(h=f([]));if(b&&h.length){n=r.data().level;if(m.ancestors&&(r.is(h)||n>g)){p=m.ancestors;0>
custom-menu-wizard.php CHANGED
@@ -3,13 +3,19 @@
3
  * Plugin Name: Custom Menu Wizard
4
  * Plugin URI: http://wordpress.org/plugins/custom-menu-wizard/
5
  * Description: Show any part of a custom menu in a Widget, or in content using a Shortcode. Customise the output with extra classes or html; filter by current menu item or a specific item; set a depth, show the parent(s), change the list style, etc. Use the included emulator to assist with the filter settings.
6
- * Version: 3.0.2
7
  * Author: Roger Barrett
8
  * Author URI: http://www.wizzud.com/
9
  * License: GPL2+
10
  */
11
  defined( 'ABSPATH' ) or exit();
12
  /*
 
 
 
 
 
 
13
  * v3.0.2 change log
14
  * - fixed bug where the shortcode shown on new instances didn't initially reflect the automatically selected menu
15
  *
@@ -120,7 +126,7 @@ if( !class_exists( 'Custom_Menu_Wizard_Plugin' ) ){
120
  //declare the main plugin class...
121
  class Custom_Menu_Wizard_Plugin {
122
 
123
- public static $version = '3.0.2';
124
  protected static $instance;
125
 
126
  /**
@@ -259,7 +265,12 @@ if( !class_exists( 'Custom_Menu_Wizard_Plugin' ) ){
259
  );
260
  foreach( $codes as $k => $v ){
261
  $j = str_replace( '-', '_', $k );
262
- $$j = '%' . like_escape( esc_sql ( $v ) ) . '%';
 
 
 
 
 
263
  }
264
 
265
  //search in all custom fields...
3
  * Plugin Name: Custom Menu Wizard
4
  * Plugin URI: http://wordpress.org/plugins/custom-menu-wizard/
5
  * Description: Show any part of a custom menu in a Widget, or in content using a Shortcode. Customise the output with extra classes or html; filter by current menu item or a specific item; set a depth, show the parent(s), change the list style, etc. Use the included emulator to assist with the filter settings.
6
+ * Version: 3.0.3
7
  * Author: Roger Barrett
8
  * Author URI: http://www.wizzud.com/
9
  * License: GPL2+
10
  */
11
  defined( 'ABSPATH' ) or exit();
12
  /*
13
+ * v3.0.3 change log
14
+ * - removed all occurrences of "Plugin " followed by "Name" from everywhere except the main plugin file (this one!) to avoid update() incorrectly reporting "invalid header" when activating straight from installation (rather than from the Plugin admin page)
15
+ * - tweak : eliminate the over-use of get_title() when determining the widget title
16
+ * - tweak : added self-terminating forward slash to generated shortcodes
17
+ * - prepare for WPv4 (avoid deprecated functions)
18
+ *
19
  * v3.0.2 change log
20
  * - fixed bug where the shortcode shown on new instances didn't initially reflect the automatically selected menu
21
  *
126
  //declare the main plugin class...
127
  class Custom_Menu_Wizard_Plugin {
128
 
129
+ public static $version = '3.0.3';
130
  protected static $instance;
131
 
132
  /**
265
  );
266
  foreach( $codes as $k => $v ){
267
  $j = str_replace( '-', '_', $k );
268
+ //like_escape deprecated in v4...
269
+ if( method_exists( $wpdb, 'esc_like' ) ){
270
+ $$j = '%' . $wpdb->esc_like( $v ) . '%';
271
+ }else{
272
+ $$j = '%' . like_escape( esc_sql ( $v ) ) . '%';
273
+ }
274
  }
275
 
276
  //search in all custom fields...
include/class.walker.php CHANGED
@@ -1,6 +1,6 @@
1
  <?php
2
  /*
3
- * Plugin Name: Custom Menu Wizard
4
  *
5
  * Custom Menu Wizard Walker class
6
  * NB: Walker_Nav_Menu class is in wp-includes/nav-menu-template.php, and is itself an
@@ -11,9 +11,9 @@ class Custom_Menu_Wizard_Walker extends Walker_Nav_Menu {
11
  /**
12
  * CMW custom variables
13
  */
14
- var $_cmw_tree;
15
- var $_cmw_lowest;
16
- var $_cmw_highest;
17
 
18
  /**
19
  * opens a sub-level with a UL or OL start-tag
@@ -21,7 +21,7 @@ class Custom_Menu_Wizard_Walker extends Walker_Nav_Menu {
21
  * @param string $output Passed by reference. Used to append additional content.
22
  * @param int $depth Depth of page. Used for padding.
23
  */
24
- function start_lvl( &$output, $depth = 0, $args = array() ) {
25
 
26
  $indent = str_repeat("\t", $depth);
27
  $listtag = empty( $args->_custom_menu_wizard['ol_sub'] ) ? 'ul' : 'ol';
@@ -35,7 +35,7 @@ class Custom_Menu_Wizard_Walker extends Walker_Nav_Menu {
35
  * @param string $output Passed by reference. Used to append additional content.
36
  * @param int $depth Depth of page. Used for padding.
37
  */
38
- function end_lvl( &$output, $depth = 0, $args = array() ) {
39
 
40
  $indent = str_repeat("\t", $depth);
41
  $listtag = empty( $args->_custom_menu_wizard['ol_sub'] ) ? 'ul' : 'ol';
@@ -52,7 +52,7 @@ class Custom_Menu_Wizard_Walker extends Walker_Nav_Menu {
52
  * @param integer $max_depth
53
  * @return string
54
  */
55
- function walk($elements, $max_depth){
56
 
57
  $args = array_slice(func_get_args(), 2);
58
  $args = $args[0];
@@ -83,7 +83,7 @@ class Custom_Menu_Wizard_Walker extends Walker_Nav_Menu {
83
  * @param array $cmw Array of widget instance settings
84
  * @return integer ID of current menu item (false if not found)
85
  */
86
- function _cmw_find_current_item( &$elements, &$cmw ){
87
  //$elements is an array of objects, indexed by position within the menu (menu_order),
88
  //starting at 1 and incrementing sequentially regardless of parentage (ie. first item is [1],
89
  //second item is [2] whether it's at root or subordinate to first item)
@@ -255,7 +255,7 @@ class Custom_Menu_Wizard_Walker extends Walker_Nav_Menu {
255
  * @param boolean $andSiblings Whether to check in $lookBelow's siblings as well
256
  * @return boolean Found (or not)
257
  */
258
- function _cmw_check_contains_item( $lookBelow, $searchFor, $andSiblings ){
259
 
260
  $rtn = in_array( $lookBelow, $this->_cmw_tree[ $searchFor ]['ancestors'] );
261
  if( !$rtn && $andSiblings ){
@@ -277,7 +277,7 @@ class Custom_Menu_Wizard_Walker extends Walker_Nav_Menu {
277
  * @param integer $kid Menu item ID
278
  * @return integer Menu item ID of kid's parent
279
  */
280
- function _cmw_get_parent( $kid ){
281
 
282
  $immediateParent = array_slice( $this->_cmw_tree[ $kid ]['ancestors'], -1, 1);
283
  return $immediateParent[0];
@@ -290,7 +290,7 @@ class Custom_Menu_Wizard_Walker extends Walker_Nav_Menu {
290
  * @param integer $itemID Menu item ID
291
  * @param string $classSuffix Suffix of class to be added to the kept items
292
  */
293
- function _cmw_include_siblings_of( $itemID, $classSuffix='sibling' ){
294
 
295
  foreach( $this->_cmw_tree[ $this->_cmw_get_parent( $itemID ) ]['kids'] as $i ){
296
  if( !$this->_cmw_tree[ $i ]['keep'] ){
@@ -310,7 +310,7 @@ class Custom_Menu_Wizard_Walker extends Walker_Nav_Menu {
310
  *
311
  * @param integer $itemID Menu item ID
312
  */
313
- function _cmw_set_keep_recursive( $itemID ){
314
 
315
  //at or above lowest?...
316
  if( $this->_cmw_tree[ $itemID ]['level'] <= $this->_cmw_lowest ){
@@ -340,7 +340,7 @@ class Custom_Menu_Wizard_Walker extends Walker_Nav_Menu {
340
  * @param integer $topLevel Uppermost level that can be kept
341
  * @param integer $bottomLevel Lowermost level that can be kept
342
  */
343
- function _cmw_legacy_set_keep_kids( $itemId, $topLevel, $bottomLevel ){
344
 
345
  for( $i = 0, $ct = count( $this->_cmw_tree[ $itemId ]['kids'] ); $i < $ct; $i++ ){
346
  $j = $this->_cmw_tree[ $itemId ]['kids'][ $i ];
@@ -363,7 +363,7 @@ class Custom_Menu_Wizard_Walker extends Walker_Nav_Menu {
363
  * @param {array} $elements Menu items
364
  * @return {array} Modified menu items
365
  */
366
- function _cmw_walk( &$args, $elements ){
367
 
368
  $cmw =& $args->_custom_menu_wizard;
369
 
@@ -647,38 +647,22 @@ class Custom_Menu_Wizard_Walker extends Walker_Nav_Menu {
647
  if( $continue ){
648
  //might we want the (original) branch item's, or root item's, title as the widget title?...
649
  if( $find_branch && $theBranchItem > 0 ){
650
- $cmw['_walker']['branch_title'] = apply_filters(
651
- 'the_title',
652
- $elements[ $this->_cmw_tree[ $theBranchItem ]['element'][0] ]->title,
653
- $elements[ $this->_cmw_tree[ $theBranchItem ]['element'][0] ]->ID
654
- );
655
  if( $this->_cmw_tree[ $theBranchItem ]['level'] > 1 ){
656
  $topOfBranch = array_slice( $this->_cmw_tree[ $theBranchItem ]['ancestors'], 1, 1 );
657
  $topOfBranch = $topOfBranch[0];
658
- $cmw['_walker']['branch_root_title'] = apply_filters(
659
- 'the_title',
660
- $elements[ $this->_cmw_tree[ $topOfBranch ]['element'][0] ]->title,
661
- $elements[ $this->_cmw_tree[ $topOfBranch ]['element'][0] ]->ID
662
- );
663
  }else{
664
  $cmw['_walker']['branch_root_title'] = $cmw['_walker']['branch_title'];
665
  }
666
  }
667
  //might we want the current item's, or root item's, title as the widget title?...
668
  if( !empty( $currentItem ) ){
669
- $cmw['_walker']['current_title'] = apply_filters(
670
- 'the_title',
671
- $elements[ $this->_cmw_tree[ $currentItem ]['element'][0] ]->title,
672
- $elements[ $this->_cmw_tree[ $currentItem ]['element'][0] ]->ID
673
- );
674
  if( $this->_cmw_tree[ $currentItem ]['level'] > 1 ){
675
  $topOfBranch = array_slice( $this->_cmw_tree[ $currentItem ]['ancestors'], 1, 1 );
676
  $topOfBranch = $topOfBranch[0];
677
- $cmw['_walker']['current_root_title'] = apply_filters(
678
- 'the_title',
679
- $elements[ $this->_cmw_tree[ $topOfBranch ]['element'][0] ]->title,
680
- $elements[ $this->_cmw_tree[ $topOfBranch ]['element'][0] ]->ID
681
- );
682
  }else{
683
  $cmw['_walker']['current_root_title'] = $cmw['_walker']['current_title'];
684
  }
@@ -764,7 +748,7 @@ class Custom_Menu_Wizard_Walker extends Walker_Nav_Menu {
764
  * @param {array} $elements Menu items
765
  * @return {array} Modified menu items
766
  */
767
- function _cmw_walk_legacy( &$args, $elements ){
768
 
769
  //NB : $elements is an array of objects, indexed by position within the menu (menu_order),
770
  //starting at 1 and incrementing sequentially regardless of parentage (ie. first item is [1],
1
  <?php
2
  /*
3
+ * Custom Menu Wizard plugin
4
  *
5
  * Custom Menu Wizard Walker class
6
  * NB: Walker_Nav_Menu class is in wp-includes/nav-menu-template.php, and is itself an
11
  /**
12
  * CMW custom variables
13
  */
14
+ private $_cmw_tree;
15
+ private $_cmw_lowest;
16
+ private $_cmw_highest;
17
 
18
  /**
19
  * opens a sub-level with a UL or OL start-tag
21
  * @param string $output Passed by reference. Used to append additional content.
22
  * @param int $depth Depth of page. Used for padding.
23
  */
24
+ public function start_lvl( &$output, $depth = 0, $args = array() ) {
25
 
26
  $indent = str_repeat("\t", $depth);
27
  $listtag = empty( $args->_custom_menu_wizard['ol_sub'] ) ? 'ul' : 'ol';
35
  * @param string $output Passed by reference. Used to append additional content.
36
  * @param int $depth Depth of page. Used for padding.
37
  */
38
+ public function end_lvl( &$output, $depth = 0, $args = array() ) {
39
 
40
  $indent = str_repeat("\t", $depth);
41
  $listtag = empty( $args->_custom_menu_wizard['ol_sub'] ) ? 'ul' : 'ol';
52
  * @param integer $max_depth
53
  * @return string
54
  */
55
+ public function walk($elements, $max_depth){
56
 
57
  $args = array_slice(func_get_args(), 2);
58
  $args = $args[0];
83
  * @param array $cmw Array of widget instance settings
84
  * @return integer ID of current menu item (false if not found)
85
  */
86
+ private function _cmw_find_current_item( &$elements, &$cmw ){
87
  //$elements is an array of objects, indexed by position within the menu (menu_order),
88
  //starting at 1 and incrementing sequentially regardless of parentage (ie. first item is [1],
89
  //second item is [2] whether it's at root or subordinate to first item)
255
  * @param boolean $andSiblings Whether to check in $lookBelow's siblings as well
256
  * @return boolean Found (or not)
257
  */
258
+ private function _cmw_check_contains_item( $lookBelow, $searchFor, $andSiblings ){
259
 
260
  $rtn = in_array( $lookBelow, $this->_cmw_tree[ $searchFor ]['ancestors'] );
261
  if( !$rtn && $andSiblings ){
277
  * @param integer $kid Menu item ID
278
  * @return integer Menu item ID of kid's parent
279
  */
280
+ private function _cmw_get_parent( $kid ){
281
 
282
  $immediateParent = array_slice( $this->_cmw_tree[ $kid ]['ancestors'], -1, 1);
283
  return $immediateParent[0];
290
  * @param integer $itemID Menu item ID
291
  * @param string $classSuffix Suffix of class to be added to the kept items
292
  */
293
+ private function _cmw_include_siblings_of( $itemID, $classSuffix='sibling' ){
294
 
295
  foreach( $this->_cmw_tree[ $this->_cmw_get_parent( $itemID ) ]['kids'] as $i ){
296
  if( !$this->_cmw_tree[ $i ]['keep'] ){
310
  *
311
  * @param integer $itemID Menu item ID
312
  */
313
+ private function _cmw_set_keep_recursive( $itemID ){
314
 
315
  //at or above lowest?...
316
  if( $this->_cmw_tree[ $itemID ]['level'] <= $this->_cmw_lowest ){
340
  * @param integer $topLevel Uppermost level that can be kept
341
  * @param integer $bottomLevel Lowermost level that can be kept
342
  */
343
+ private function _cmw_legacy_set_keep_kids( $itemId, $topLevel, $bottomLevel ){
344
 
345
  for( $i = 0, $ct = count( $this->_cmw_tree[ $itemId ]['kids'] ); $i < $ct; $i++ ){
346
  $j = $this->_cmw_tree[ $itemId ]['kids'][ $i ];
363
  * @param {array} $elements Menu items
364
  * @return {array} Modified menu items
365
  */
366
+ private function _cmw_walk( &$args, $elements ){
367
 
368
  $cmw =& $args->_custom_menu_wizard;
369
 
647
  if( $continue ){
648
  //might we want the (original) branch item's, or root item's, title as the widget title?...
649
  if( $find_branch && $theBranchItem > 0 ){
650
+ $cmw['_walker']['branch_title'] = $elements[ $this->_cmw_tree[ $theBranchItem ]['element'][0] ]->title;
 
 
 
 
651
  if( $this->_cmw_tree[ $theBranchItem ]['level'] > 1 ){
652
  $topOfBranch = array_slice( $this->_cmw_tree[ $theBranchItem ]['ancestors'], 1, 1 );
653
  $topOfBranch = $topOfBranch[0];
654
+ $cmw['_walker']['branch_root_title'] = $elements[ $this->_cmw_tree[ $topOfBranch ]['element'][0] ]->title;
 
 
 
 
655
  }else{
656
  $cmw['_walker']['branch_root_title'] = $cmw['_walker']['branch_title'];
657
  }
658
  }
659
  //might we want the current item's, or root item's, title as the widget title?...
660
  if( !empty( $currentItem ) ){
661
+ $cmw['_walker']['current_title'] = $elements[ $this->_cmw_tree[ $currentItem ]['element'][0] ]->title;
 
 
 
 
662
  if( $this->_cmw_tree[ $currentItem ]['level'] > 1 ){
663
  $topOfBranch = array_slice( $this->_cmw_tree[ $currentItem ]['ancestors'], 1, 1 );
664
  $topOfBranch = $topOfBranch[0];
665
+ $cmw['_walker']['current_root_title'] = $elements[ $this->_cmw_tree[ $topOfBranch ]['element'][0] ]->title;
 
 
 
 
666
  }else{
667
  $cmw['_walker']['current_root_title'] = $cmw['_walker']['current_title'];
668
  }
748
  * @param {array} $elements Menu items
749
  * @return {array} Modified menu items
750
  */
751
+ private function _cmw_walk_legacy( &$args, $elements ){
752
 
753
  //NB : $elements is an array of objects, indexed by position within the menu (menu_order),
754
  //starting at 1 and incrementing sequentially regardless of parentage (ie. first item is [1],
include/class.widget.php CHANGED
@@ -1,6 +1,6 @@
1
  <?php
2
  /*
3
- * Plugin Name: Custom Menu Wizard
4
  *
5
  * Custom Menu Wizard Widget class
6
  */
@@ -9,7 +9,7 @@ class Custom_Menu_Wizard_Widget extends WP_Widget {
9
  /**
10
  * class constructor
11
  */
12
- function __construct() {
13
 
14
  parent::__construct(
15
  'custom-menu-wizard',
@@ -33,7 +33,7 @@ class Custom_Menu_Wizard_Widget extends WP_Widget {
33
  *
34
  * @param array $instance Widget settings
35
  */
36
- function form( $instance ) {
37
 
38
  //raised June 2014 : problem...
39
  //using the widget_form_callback filter (as Widget Title Links plugin does, which raised the issue) it is perfectly
@@ -626,7 +626,7 @@ class Custom_Menu_Wizard_Widget extends WP_Widget {
626
  * @param array $old_instance Old widget settings
627
  * @return array Sanitized widget settings
628
  */
629
- function update( $new_instance, $old_instance ) {
630
 
631
  //call the legacy update method for updates to existing widgets that don't have a version number (old format)...
632
  if( empty( $new_instance['cmwv'] ) ){
@@ -647,12 +647,12 @@ class Custom_Menu_Wizard_Widget extends WP_Widget {
647
  *
648
  * @filters : custom_menu_wizard_nav_params array of params that will be sent to wp_nav_menu(), array of instance settings, id base
649
  * custom_menu_wizard_settings_pre_widget array of instance settings, id base
650
- * custom_menu_wizard_widget_output HTML output string, array of instance settings, id base
651
  *
652
  * @param object $args Widget arguments
653
  * @param array $instance Configuration for this widget instance
654
  */
655
- function widget( $args, $instance ) {
656
 
657
  //call the legacy widget method for producing existing widgets that don't have a version number (old format)...
658
  if( empty( $instance['cmwv'] ) ){
@@ -663,8 +663,6 @@ class Custom_Menu_Wizard_Widget extends WP_Widget {
663
  //sanitize $instance...
664
  $instance = $this->cmw_settings( $instance, array(), __FUNCTION__ );
665
 
666
- extract( $args, EXTR_SKIP );
667
-
668
  //v1.1.0 As of WP v3.6, wp_nav_menu() automatically prevents any HTML output if there are no items...
669
  $instance['hide_empty'] = $instance['hide_empty'] && $this->cmw_wp_version('3.6');
670
 
@@ -713,8 +711,12 @@ class Custom_Menu_Wizard_Widget extends WP_Widget {
713
  );
714
  //for the walker's use...
715
  $params['_custom_menu_wizard']['_walker'] = array();
716
- //set wrapper to UL or OL...
 
 
 
717
  $dataCMWS = empty( $instance['cmws_off'] ) ? " data-cmws='" . esc_attr( $this->cmw_shortcode( $instance, true ) ) . "'" : '';
 
718
  if( $instance['ol_root'] ){
719
  $params['items_wrap'] = '<ol id="%1$s" class="%2$s" data-cmwv="' . $instance['cmwv'] . '"' . $dataCMWS . '>%3$s</ol>';
720
  }else{
@@ -766,25 +768,26 @@ class Custom_Menu_Wizard_Widget extends WP_Widget {
766
  $out );
767
 
768
  //try to add widget_class (if specified) to before_widget...
769
- if( !empty( $instance['widget_class'] ) && !empty( $before_widget ) ){
770
- //$before_widget is usually just a DIV start-tag, with an id and a class; if it
771
  //gets more complicated than that then this may not work as expected...
772
- if( preg_match( '/^<[^>]+?class=["\']/', $before_widget ) > 0 ){
773
  //...already has a class attribute : prepend mine...
774
- $before_widget = preg_replace( '/(class=["\'])/', '$1' . $instance['widget_class'] . ' ', $before_widget, 1 );
775
  }else{
776
  //...doesn't currently have a class : add class attribute...
777
- $before_widget = preg_replace( '/^(<\w+)(\s|>)/', '$1 class="' . $instance['widget_class'] . '"$2', $before_widget );
778
  }
779
  }
780
 
781
  if( !empty( $title ) ){
782
- $out = $before_title . $title . $after_title . $out;
783
  }
784
- $out = $before_widget . $out . $after_widget;
785
  //allow a filter to modify the entire output...
786
- //eg. add_filter( 'custom_menu_wizard_widget_output', [filter_function], 10, 3 ) => $output (HTML string)
787
- echo apply_filters( 'custom_menu_wizard_widget_output', $out, $instance, $this->id_base );
 
788
  }
789
  }
790
  }
@@ -794,7 +797,7 @@ class Custom_Menu_Wizard_Widget extends WP_Widget {
794
  /**
795
  * outputs an assist anchor
796
  */
797
- function cmw_assist_link(){
798
 
799
  //don't really need to worry about the id for non-javascript enabled usage because the css hides the
800
  //button, but it doesn't hurt so I've left it in...
@@ -808,7 +811,7 @@ class Custom_Menu_Wizard_Widget extends WP_Widget {
808
  /**
809
  * outputs the HTML to close off a collapsible/expandable group of settings
810
  */
811
- function cmw_close_a_field_section(){
812
 
813
  ?></div><?php
814
 
@@ -821,7 +824,8 @@ class Custom_Menu_Wizard_Widget extends WP_Widget {
821
  * @param string $action 'pop' or 'push'
822
  * @param boolean $test What to push
823
  */
824
- function cmw_disableif( $action = 'echo', $test = false ){
 
825
  if( !isset( $this->_cmw_disableif ) ){
826
  $this->_cmw_disableif = array( '' );
827
  }
@@ -846,6 +850,7 @@ class Custom_Menu_Wizard_Widget extends WP_Widget {
846
  $e = array_slice( $this->_cmw_disableif, -1 );
847
  echo $e[0];
848
  }
 
849
  }
850
 
851
  /**
@@ -862,7 +867,7 @@ class Custom_Menu_Wizard_Widget extends WP_Widget {
862
  * @param object $args
863
  * @return array Menu items
864
  */
865
- function cmw_filter_check_for_no_items($items, $args){
866
 
867
  if( !empty( $args->_custom_menu_wizard ) && empty( $items ) ){
868
  add_filter( 'wp_nav_menu', array( $this, 'cmw_filter_no_output_when_empty' ), 65532, 2 );
@@ -884,7 +889,7 @@ class Custom_Menu_Wizard_Widget extends WP_Widget {
884
  * @param object $args
885
  * @return string HTML for the menu
886
  */
887
- function cmw_filter_no_output_when_empty($nav_menu, $args){
888
 
889
  remove_filter( 'wp_nav_menu', array( $this, __FUNCTION__ ), 65532, 2 );
890
  return empty( $args->_custom_menu_wizard ) ? $nav_menu : '';
@@ -900,7 +905,7 @@ class Custom_Menu_Wizard_Widget extends WP_Widget {
900
  * @param object $args
901
  * @return array Menu items
902
  */
903
- function cmw_filter_walker_items( $items, $args ){
904
 
905
  if( !empty( $args->_custom_menu_wizard['_walker'] ) ){
906
  $this->_cmw_walker = $args->_custom_menu_wizard['_walker'];
@@ -916,7 +921,7 @@ class Custom_Menu_Wizard_Widget extends WP_Widget {
916
  * @param string $field Field name
917
  * @param array $params Attribute values
918
  */
919
- function cmw_formfield_checkbox( &$instance, $field, $params ){
920
 
921
  $labelClass = empty( $params['lclass'] ) ? '' : $params['lclass'];
922
  $fieldClass = empty( $params['fclass'] ) ? '' : $params['fclass'];
@@ -943,7 +948,7 @@ class Custom_Menu_Wizard_Widget extends WP_Widget {
943
  * @param string $field Field name
944
  * @param array $params Attribute values
945
  */
946
- function cmw_formfield_textbox( &$instance, $field, $params ){
947
 
948
  $fieldClass = empty( $params['fclass'] ) ? '' : $params['fclass'];
949
 
@@ -971,7 +976,7 @@ class Custom_Menu_Wizard_Widget extends WP_Widget {
971
  * @param integer $selectedMenu (by reference) The instance setting to check against for a menu to be "selected"
972
  * @return array
973
  */
974
- function cmw_get_custom_menus( &$selectedMenu ){
975
 
976
  $findSM = $selectedMenu > 0;
977
  $menus = wp_get_nav_menus( array( 'orderby' => 'name' ) );
@@ -1013,7 +1018,7 @@ class Custom_Menu_Wizard_Widget extends WP_Widget {
1013
  * @param integer $selectedItem The instance setting to check against for an menu item to be "selected"
1014
  * @return array|boolean
1015
  */
1016
- function cmw_scan_menus( $selectedMenu, $selectedItem ){
1017
 
1018
  //create the options for the menu select & branch select...
1019
  // IE is a pita when it comes to SELECTs because it ignores any styling on OPTGROUPs and OPTIONs, so I'm using
@@ -1048,7 +1053,7 @@ class Custom_Menu_Wizard_Widget extends WP_Widget {
1048
  foreach( $menu->_items as $item ){
1049
  //exclude orphans!
1050
  if( isset($itemindents[ $item->menu_item_parent ])){
1051
- $title = apply_filters( 'the_title', $item->title, $item->ID );
1052
  $level = $itemindents[ $item->menu_item_parent ] + 1;
1053
 
1054
  $itemindents[ $item->ID ] = $level;
@@ -1067,11 +1072,11 @@ class Custom_Menu_Wizard_Widget extends WP_Widget {
1067
  $rtn['selectedBranchName'] = $title;
1068
  }
1069
  $rtn['selectedOptgroup'][ $sogCt ] .= '<option value="' . $item->ID . '" ' . $selected . ' data-cmw-level="' . $level . '">';
1070
- $rtn['selectedOptgroup'][ $sogCt ] .= str_repeat( '&nbsp;', ($level - 1) * 3 ) . $title . '</option>';
1071
  }
1072
  //don't set "selected" on the big list...
1073
  $menuGrpOpts .= '<option value="' . $item->ID . '" data-cmw-level="' . $level . '">';
1074
- $menuGrpOpts .= str_repeat( '&nbsp;', ($level - 1) * 3 ) . $title . '</option>';
1075
  }
1076
  }
1077
 
@@ -1123,7 +1128,7 @@ class Custom_Menu_Wizard_Widget extends WP_Widget {
1123
  * @param string $text Label
1124
  * @param string $fname Field name
1125
  */
1126
- function cmw_open_a_field_section( &$instance, $text, $fname ){
1127
 
1128
  $hashid = $this->get_field_id( 'cmw' . ++$this->_cmw_hash_ct );
1129
  ?>
@@ -1143,7 +1148,7 @@ class Custom_Menu_Wizard_Widget extends WP_Widget {
1143
  * @param string $v Version to test for lower than
1144
  * @return boolean
1145
  */
1146
- function cmw_wp_version( $v, $gte=false ){
1147
  global $wp_version;
1148
 
1149
  $rtn = version_compare( strtolower( $wp_version ), $v . 'a', '<' );
@@ -1159,7 +1164,7 @@ class Custom_Menu_Wizard_Widget extends WP_Widget {
1159
  * @param string Name of the calling method
1160
  * @return array Sanitized widget settings
1161
  */
1162
- function cmw_settings( $from_instance, $base_instance, $method = 'update' ){
1163
 
1164
  /* old (pre v3) settings...
1165
  //switches...
@@ -1316,7 +1321,7 @@ class Custom_Menu_Wizard_Widget extends WP_Widget {
1316
  * @param array $instance
1317
  * @return string
1318
  */
1319
- function cmw_shortcode( $instance, $asJSON=false ){
1320
 
1321
  $args = array(
1322
  'menu' => $instance['menu']
@@ -1444,7 +1449,7 @@ class Custom_Menu_Wizard_Widget extends WP_Widget {
1444
  unset( $args );
1445
 
1446
  //NB at v3.0.0, the shortcode changed from custom_menu_wizard to cmwizard (the previous version is still supported)
1447
- return $asJSON ? json_encode( $m ) : '[cmwizard ' . implode( ' ', $m ) . ']';
1448
 
1449
  } //end cmw_shortcode()
1450
 
@@ -1461,7 +1466,7 @@ class Custom_Menu_Wizard_Widget extends WP_Widget {
1461
  *
1462
  * @param array $instance Widget settings
1463
  */
1464
- function cmw_legacy_form( $instance ) {
1465
 
1466
  //sanitize $instance...
1467
  $instance = $this->cmw_legacy_settings( $instance, array(), 'form' );
@@ -1859,7 +1864,7 @@ class Custom_Menu_Wizard_Widget extends WP_Widget {
1859
  * @param string $method Name suffix of the calling method
1860
  * @return array Sanitized widget settings
1861
  */
1862
- function cmw_legacy_settings( $from_instance, $base_instance, $method = 'update' ){
1863
 
1864
  $instance = is_array( $base_instance ) ? $base_instance : array();
1865
 
@@ -1990,7 +1995,7 @@ class Custom_Menu_Wizard_Widget extends WP_Widget {
1990
  * @param array $old_instance Old widget settings
1991
  * @return array Sanitized widget settings
1992
  */
1993
- function cmw_legacy_update( $new_instance, $old_instance ){
1994
 
1995
  //allow a filter to return true, whereby updates to legacy widgets are disallowed...
1996
  //eg. apply_filter( 'custom_menu_wizard_prevent_legacy_updates', [filter function], 10, 1 ) => true
@@ -2013,18 +2018,16 @@ class Custom_Menu_Wizard_Widget extends WP_Widget {
2013
  *
2014
  * @filters : custom_menu_wizard_nav_params array of params that will be sent to wp_nav_menu(), array of instance settings, id base
2015
  * custom_menu_wizard_settings_pre_widget array of instance settings, id base
2016
- * custom_menu_wizard_widget_output HTML output string, array of instance settings, id base
2017
  *
2018
  * @param object $args Widget arguments
2019
  * @param array $instance Configuration for this widget instance
2020
  */
2021
- function cmw_legacy_widget( $args, $instance ) {
2022
 
2023
  //sanitize $instance...
2024
  $instance = $this->cmw_legacy_settings( $instance, array(), 'widget' );
2025
 
2026
- extract( $args, EXTR_SKIP );
2027
-
2028
  //v1.1.0 As of WP v3.6, wp_nav_menu() automatically prevents any HTML output if there are no items...
2029
  $instance['hide_empty'] = $instance['hide_empty'] && $this->cmw_wp_version('3.6');
2030
 
@@ -2040,12 +2043,12 @@ class Custom_Menu_Wizard_Widget extends WP_Widget {
2040
  if ( !empty( $menu ) ){
2041
 
2042
  if( !empty( $instance['widget_class'] ) ){
2043
- //$before_widget is usually just a DIV start-tag, with an id and a class; if it
2044
  //gets more complicated than that then this may not work as expected...
2045
- if( preg_match( '/^<[^>]+?class=["\']/', $before_widget ) > 0 ){
2046
- $before_widget = preg_replace( '/(class=["\'])/', '$1' . $instance['widget_class'] . ' ', $before_widget, 1 );
2047
  }else{
2048
- $before_widget = preg_replace( '/^(<\w+)(\s|>)/', '$1 class="' . $instance['widget_class'] . '"$2', $before_widget );
2049
  }
2050
  }
2051
 
@@ -2126,12 +2129,12 @@ class Custom_Menu_Wizard_Widget extends WP_Widget {
2126
  $out );
2127
 
2128
  if ( !empty($title) ){
2129
- $out = $before_title . apply_filters('widget_title', $title, $instance, $this->id_base) . $after_title . $out;
2130
  }
2131
- $out = $before_widget . $out . $after_widget;
2132
  //allow a filter to modify the entire output...
2133
- //eg. add_filter( 'custom_menu_wizard_widget_output', [filter_function], 10, 3 ) => $output (HTML string)
2134
- echo apply_filters( 'custom_menu_wizard_widget_output', $out, $instance, $this->id_base );
2135
  }
2136
  }
2137
  }
1
  <?php
2
  /*
3
+ * Custom Menu Wizard plugin
4
  *
5
  * Custom Menu Wizard Widget class
6
  */
9
  /**
10
  * class constructor
11
  */
12
+ public function __construct() {
13
 
14
  parent::__construct(
15
  'custom-menu-wizard',
33
  *
34
  * @param array $instance Widget settings
35
  */
36
+ public function form( $instance ) {
37
 
38
  //raised June 2014 : problem...
39
  //using the widget_form_callback filter (as Widget Title Links plugin does, which raised the issue) it is perfectly
626
  * @param array $old_instance Old widget settings
627
  * @return array Sanitized widget settings
628
  */
629
+ public function update( $new_instance, $old_instance ) {
630
 
631
  //call the legacy update method for updates to existing widgets that don't have a version number (old format)...
632
  if( empty( $new_instance['cmwv'] ) ){
647
  *
648
  * @filters : custom_menu_wizard_nav_params array of params that will be sent to wp_nav_menu(), array of instance settings, id base
649
  * custom_menu_wizard_settings_pre_widget array of instance settings, id base
650
+ * custom_menu_wizard_widget_output HTML output string, array of instance settings, id base, $args
651
  *
652
  * @param object $args Widget arguments
653
  * @param array $instance Configuration for this widget instance
654
  */
655
+ public function widget( $args, $instance ) {
656
 
657
  //call the legacy widget method for producing existing widgets that don't have a version number (old format)...
658
  if( empty( $instance['cmwv'] ) ){
663
  //sanitize $instance...
664
  $instance = $this->cmw_settings( $instance, array(), __FUNCTION__ );
665
 
 
 
666
  //v1.1.0 As of WP v3.6, wp_nav_menu() automatically prevents any HTML output if there are no items...
667
  $instance['hide_empty'] = $instance['hide_empty'] && $this->cmw_wp_version('3.6');
668
 
711
  );
712
  //for the walker's use...
713
  $params['_custom_menu_wizard']['_walker'] = array();
714
+ //unless told not to, put the shortcode equiv. into a data item...
715
+ //NB: to turn this off (example):
716
+ // add_filter( 'custom_menu_wizard_settings_pre_widget', 'cmw_no_cmws', 10, 2 );
717
+ // function cmw_no_cmws( $instance, $id_base ){ $instance['cmws_off'] = true; return $instance; }
718
  $dataCMWS = empty( $instance['cmws_off'] ) ? " data-cmws='" . esc_attr( $this->cmw_shortcode( $instance, true ) ) . "'" : '';
719
+ //set wrapper to UL or OL...
720
  if( $instance['ol_root'] ){
721
  $params['items_wrap'] = '<ol id="%1$s" class="%2$s" data-cmwv="' . $instance['cmwv'] . '"' . $dataCMWS . '>%3$s</ol>';
722
  }else{
768
  $out );
769
 
770
  //try to add widget_class (if specified) to before_widget...
771
+ if( !empty( $instance['widget_class'] ) && !empty( $args['before_widget'] ) ){
772
+ //$args['before_widget'] is usually just a DIV start-tag, with an id and a class; if it
773
  //gets more complicated than that then this may not work as expected...
774
+ if( preg_match( '/^<[^>]+?class=["\']/', $args['before_widget'] ) > 0 ){
775
  //...already has a class attribute : prepend mine...
776
+ $args['before_widget'] = preg_replace( '/(class=["\'])/', '$1' . $instance['widget_class'] . ' ', $args['before_widget'], 1 );
777
  }else{
778
  //...doesn't currently have a class : add class attribute...
779
+ $args['before_widget'] = preg_replace( '/^(<\w+)(\s|>)/', '$1 class="' . $instance['widget_class'] . '"$2', $args['before_widget'] );
780
  }
781
  }
782
 
783
  if( !empty( $title ) ){
784
+ $out = $args['before_title'] . $title . $args['after_title'] . $out;
785
  }
786
+ $out = $args['before_widget'] . $out . $args['after_widget'];
787
  //allow a filter to modify the entire output...
788
+ //eg. add_filter( 'custom_menu_wizard_widget_output', [filter_function], 10, 4 ) => $output (HTML string)
789
+ //NB 4th parameter ($args) added at v3.0.3
790
+ echo apply_filters( 'custom_menu_wizard_widget_output', $out, $instance, $this->id_base, $args );
791
  }
792
  }
793
  }
797
  /**
798
  * outputs an assist anchor
799
  */
800
+ public function cmw_assist_link(){
801
 
802
  //don't really need to worry about the id for non-javascript enabled usage because the css hides the
803
  //button, but it doesn't hurt so I've left it in...
811
  /**
812
  * outputs the HTML to close off a collapsible/expandable group of settings
813
  */
814
+ public function cmw_close_a_field_section(){
815
 
816
  ?></div><?php
817
 
824
  * @param string $action 'pop' or 'push'
825
  * @param boolean $test What to push
826
  */
827
+ public function cmw_disableif( $action = 'echo', $test = false ){
828
+
829
  if( !isset( $this->_cmw_disableif ) ){
830
  $this->_cmw_disableif = array( '' );
831
  }
850
  $e = array_slice( $this->_cmw_disableif, -1 );
851
  echo $e[0];
852
  }
853
+
854
  }
855
 
856
  /**
867
  * @param object $args
868
  * @return array Menu items
869
  */
870
+ public function cmw_filter_check_for_no_items($items, $args){
871
 
872
  if( !empty( $args->_custom_menu_wizard ) && empty( $items ) ){
873
  add_filter( 'wp_nav_menu', array( $this, 'cmw_filter_no_output_when_empty' ), 65532, 2 );
889
  * @param object $args
890
  * @return string HTML for the menu
891
  */
892
+ public function cmw_filter_no_output_when_empty($nav_menu, $args){
893
 
894
  remove_filter( 'wp_nav_menu', array( $this, __FUNCTION__ ), 65532, 2 );
895
  return empty( $args->_custom_menu_wizard ) ? $nav_menu : '';
905
  * @param object $args
906
  * @return array Menu items
907
  */
908
+ public function cmw_filter_walker_items( $items, $args ){
909
 
910
  if( !empty( $args->_custom_menu_wizard['_walker'] ) ){
911
  $this->_cmw_walker = $args->_custom_menu_wizard['_walker'];
921
  * @param string $field Field name
922
  * @param array $params Attribute values
923
  */
924
+ public function cmw_formfield_checkbox( &$instance, $field, $params ){
925
 
926
  $labelClass = empty( $params['lclass'] ) ? '' : $params['lclass'];
927
  $fieldClass = empty( $params['fclass'] ) ? '' : $params['fclass'];
948
  * @param string $field Field name
949
  * @param array $params Attribute values
950
  */
951
+ public function cmw_formfield_textbox( &$instance, $field, $params ){
952
 
953
  $fieldClass = empty( $params['fclass'] ) ? '' : $params['fclass'];
954
 
976
  * @param integer $selectedMenu (by reference) The instance setting to check against for a menu to be "selected"
977
  * @return array
978
  */
979
+ public function cmw_get_custom_menus( &$selectedMenu ){
980
 
981
  $findSM = $selectedMenu > 0;
982
  $menus = wp_get_nav_menus( array( 'orderby' => 'name' ) );
1018
  * @param integer $selectedItem The instance setting to check against for an menu item to be "selected"
1019
  * @return array|boolean
1020
  */
1021
+ public function cmw_scan_menus( $selectedMenu, $selectedItem ){
1022
 
1023
  //create the options for the menu select & branch select...
1024
  // IE is a pita when it comes to SELECTs because it ignores any styling on OPTGROUPs and OPTIONs, so I'm using
1053
  foreach( $menu->_items as $item ){
1054
  //exclude orphans!
1055
  if( isset($itemindents[ $item->menu_item_parent ])){
1056
+ $title = $item->title;
1057
  $level = $itemindents[ $item->menu_item_parent ] + 1;
1058
 
1059
  $itemindents[ $item->ID ] = $level;
1072
  $rtn['selectedBranchName'] = $title;
1073
  }
1074
  $rtn['selectedOptgroup'][ $sogCt ] .= '<option value="' . $item->ID . '" ' . $selected . ' data-cmw-level="' . $level . '">';
1075
+ $rtn['selectedOptgroup'][ $sogCt ] .= str_repeat( '&nbsp;', ($level - 1) * 3 ) . esc_attr( $title ) . '</option>';
1076
  }
1077
  //don't set "selected" on the big list...
1078
  $menuGrpOpts .= '<option value="' . $item->ID . '" data-cmw-level="' . $level . '">';
1079
+ $menuGrpOpts .= str_repeat( '&nbsp;', ($level - 1) * 3 ) . esc_attr( $title ) . '</option>';
1080
  }
1081
  }
1082
 
1128
  * @param string $text Label
1129
  * @param string $fname Field name
1130
  */
1131
+ public function cmw_open_a_field_section( &$instance, $text, $fname ){
1132
 
1133
  $hashid = $this->get_field_id( 'cmw' . ++$this->_cmw_hash_ct );
1134
  ?>
1148
  * @param string $v Version to test for lower than
1149
  * @return boolean
1150
  */
1151
+ public function cmw_wp_version( $v, $gte=false ){
1152
  global $wp_version;
1153
 
1154
  $rtn = version_compare( strtolower( $wp_version ), $v . 'a', '<' );
1164
  * @param string Name of the calling method
1165
  * @return array Sanitized widget settings
1166
  */
1167
+ public function cmw_settings( $from_instance, $base_instance, $method = 'update' ){
1168
 
1169
  /* old (pre v3) settings...
1170
  //switches...
1321
  * @param array $instance
1322
  * @return string
1323
  */
1324
+ public function cmw_shortcode( $instance, $asJSON=false ){
1325
 
1326
  $args = array(
1327
  'menu' => $instance['menu']
1449
  unset( $args );
1450
 
1451
  //NB at v3.0.0, the shortcode changed from custom_menu_wizard to cmwizard (the previous version is still supported)
1452
+ return $asJSON ? json_encode( $m ) : '[cmwizard ' . implode( ' ', $m ) . '/]';
1453
 
1454
  } //end cmw_shortcode()
1455
 
1466
  *
1467
  * @param array $instance Widget settings
1468
  */
1469
+ public function cmw_legacy_form( $instance ) {
1470
 
1471
  //sanitize $instance...
1472
  $instance = $this->cmw_legacy_settings( $instance, array(), 'form' );
1864
  * @param string $method Name suffix of the calling method
1865
  * @return array Sanitized widget settings
1866
  */
1867
+ public function cmw_legacy_settings( $from_instance, $base_instance, $method = 'update' ){
1868
 
1869
  $instance = is_array( $base_instance ) ? $base_instance : array();
1870
 
1995
  * @param array $old_instance Old widget settings
1996
  * @return array Sanitized widget settings
1997
  */
1998
+ public function cmw_legacy_update( $new_instance, $old_instance ){
1999
 
2000
  //allow a filter to return true, whereby updates to legacy widgets are disallowed...
2001
  //eg. apply_filter( 'custom_menu_wizard_prevent_legacy_updates', [filter function], 10, 1 ) => true
2018
  *
2019
  * @filters : custom_menu_wizard_nav_params array of params that will be sent to wp_nav_menu(), array of instance settings, id base
2020
  * custom_menu_wizard_settings_pre_widget array of instance settings, id base
2021
+ * custom_menu_wizard_widget_output HTML output string, array of instance settings, id base, $args
2022
  *
2023
  * @param object $args Widget arguments
2024
  * @param array $instance Configuration for this widget instance
2025
  */
2026
+ public function cmw_legacy_widget( $args, $instance ) {
2027
 
2028
  //sanitize $instance...
2029
  $instance = $this->cmw_legacy_settings( $instance, array(), 'widget' );
2030
 
 
 
2031
  //v1.1.0 As of WP v3.6, wp_nav_menu() automatically prevents any HTML output if there are no items...
2032
  $instance['hide_empty'] = $instance['hide_empty'] && $this->cmw_wp_version('3.6');
2033
 
2043
  if ( !empty( $menu ) ){
2044
 
2045
  if( !empty( $instance['widget_class'] ) ){
2046
+ //$args['before_widget'] is usually just a DIV start-tag, with an id and a class; if it
2047
  //gets more complicated than that then this may not work as expected...
2048
+ if( preg_match( '/^<[^>]+?class=["\']/', $args['before_widget'] ) > 0 ){
2049
+ $args['before_widget'] = preg_replace( '/(class=["\'])/', '$1' . $instance['widget_class'] . ' ', $args['before_widget'], 1 );
2050
  }else{
2051
+ $args['before_widget'] = preg_replace( '/^(<\w+)(\s|>)/', '$1 class="' . $instance['widget_class'] . '"$2', $args['before_widget'] );
2052
  }
2053
  }
2054
 
2129
  $out );
2130
 
2131
  if ( !empty($title) ){
2132
+ $out = $args['before_title'] . apply_filters('widget_title', $title, $instance, $this->id_base) . $args['after_title'] . $out;
2133
  }
2134
+ $out = $args['before_widget'] . $out . $args['after_widget'];
2135
  //allow a filter to modify the entire output...
2136
+ //eg. add_filter( 'custom_menu_wizard_widget_output', [filter_function], 10, 4 ) => $output (HTML string)
2137
+ echo apply_filters( 'custom_menu_wizard_widget_output', $out, $instance, $this->id_base, $args );
2138
  }
2139
  }
2140
  }
readme.txt CHANGED
@@ -4,7 +4,7 @@ Donate link: https://www.paypal.com/cgi-bin/webscr?cmd=_s-xclick&hosted_button_i
4
  Tags: menu,widget,widgets,navigation,nav,custom menus,custom menu,partial menu,current item,current page,menu level,menu branch,menu shortcode,menu widget,advanced,enhanced
5
  Requires at least: 3.6
6
  Tested up to: 3.9
7
- Stable tag: 3.0.2
8
  License: GPLv2 or Later
9
 
10
  Show branches or levels of your menu in a widget, or in content using a shortcode, with full customisation.
@@ -45,7 +45,7 @@ there are probably a couple of very common scenarios:
45
  * Open the FILTERS section :
46
  * under Primary Filter, click on the *Branch* radio
47
  * Save the widget!
48
- * *Equivalent shortcode resembles `[cmwizard menu=N title="Your Title" branch=current]`*
49
 
50
  2. Show just the descendants of the current menu item (if there are any)...
51
  * Drag a new Custom Menu Wizard widget into the sidebar, and give it a title (if you want one)
@@ -54,7 +54,7 @@ there are probably a couple of very common scenarios:
54
  * under Primary Filter, click on the *Branch* radio
55
  * under Secondary Filter, set *Starting at* to "+1 (children)"
56
  * Save the widget!
57
- * *Equivalent shortcode resembles `[cmwizard menu=N title="Your Title" branch=current start_at="+1"]`*
58
 
59
  If you like this widget (or if you don't?), please consider taking a moment or two to give it a
60
  [Review](http://wordpress.org/support/view/plugin-reviews/custom-menu-wizard) : it helps others, and gives me valuable feedback.
@@ -528,32 +528,32 @@ If enabled it will return a list of posts that contain a CMW shortcode. If `find
528
  notice of is `title`, which will be output (if supplied) as an H3 in front of the list. The information provided by this utility is also available
529
  from any widget's "assist".
530
 
531
- Example : `[cmwizard findme=1 title="Posts containing a CMW shortcode..."]`
532
 
533
  == Shortcode Examples ==
534
 
535
  * Show the entire "main" menu
536
 
537
  `
538
- [cmwizard menu=main]
539
  `
540
 
541
  * Show the children of the current menu item within the "main" menu, for unlimited depth, setting the widget title from the current menu item
542
 
543
  `
544
- [cmwizard menu=main branch=current start_at=children title_from=current]
545
  `
546
 
547
  * From the "animals" menu, show all the items *immediately* below "Small Dogs", plus "Small Dogs" and its sibling items, as ordered lists
548
 
549
  `
550
- [cmwizard menu="animals" branch="small dogs" depth=2 include="siblings" ol_root=1 ol_sub=1]
551
  `
552
 
553
  * From the "animals" menu, show the entire "Small Animals" branch, with the sole exception of the "Small Animals" item itself, whenever "Small Animals" or one of its descendants is the current menu item
554
 
555
  `
556
- [cmwizard menu="animals" branch="small animals" start_at=children contains_current=primary]
557
  `
558
 
559
  == Installation ==
@@ -652,7 +652,7 @@ contains any CMW shortcode. Each entry is a link that opens the item in a new ta
652
  post type, id, whether the shortcode(s) are in content and/or meta data, and the shortcode(s) concerned.
653
  This utility does not check things like text widgets, plugin-specific tables, theme-provided textareas, etc.
654
 
655
- There is also an extension to the shortcode - `[cmwizard findme=1]` - that will output the same information, should you not be able to use
656
  the "assist" (for some unknown reason). You may optionally provide a title attribute; any other attributes are ignored.
657
  Note that output from this shortcode extension is restricted to users with edit_pages capability.
658
 
@@ -669,6 +669,12 @@ Note that output from this shortcode extension is restricted to users with edit_
669
 
670
  == Changelog ==
671
 
 
 
 
 
 
 
672
  = 3.0.2 =
673
  * bugfix : the shortcode display on new instances of the widget (in admin) did not initially reflect the automatically-selected menu
674
 
@@ -775,6 +781,11 @@ Note that output from this shortcode extension is restricted to users with edit_
775
 
776
  == Upgrade Notice ==
777
 
 
 
 
 
 
778
  = 3.0.2 =
779
  Fixed a bug where the shortcode displayed on new instances of the widget (in admin) did not initially reflect the automatically-selected menu
780
 
4
  Tags: menu,widget,widgets,navigation,nav,custom menus,custom menu,partial menu,current item,current page,menu level,menu branch,menu shortcode,menu widget,advanced,enhanced
5
  Requires at least: 3.6
6
  Tested up to: 3.9
7
+ Stable tag: 3.0.3
8
  License: GPLv2 or Later
9
 
10
  Show branches or levels of your menu in a widget, or in content using a shortcode, with full customisation.
45
  * Open the FILTERS section :
46
  * under Primary Filter, click on the *Branch* radio
47
  * Save the widget!
48
+ * *Equivalent shortcode resembles `[cmwizard menu=N title="Your Title" branch=current/]`*
49
 
50
  2. Show just the descendants of the current menu item (if there are any)...
51
  * Drag a new Custom Menu Wizard widget into the sidebar, and give it a title (if you want one)
54
  * under Primary Filter, click on the *Branch* radio
55
  * under Secondary Filter, set *Starting at* to "+1 (children)"
56
  * Save the widget!
57
+ * *Equivalent shortcode resembles `[cmwizard menu=N title="Your Title" branch=current start_at="+1"/]`*
58
 
59
  If you like this widget (or if you don't?), please consider taking a moment or two to give it a
60
  [Review](http://wordpress.org/support/view/plugin-reviews/custom-menu-wizard) : it helps others, and gives me valuable feedback.
528
  notice of is `title`, which will be output (if supplied) as an H3 in front of the list. The information provided by this utility is also available
529
  from any widget's "assist".
530
 
531
+ Example : `[cmwizard findme=1 title="Posts containing a CMW shortcode..."/]`
532
 
533
  == Shortcode Examples ==
534
 
535
  * Show the entire "main" menu
536
 
537
  `
538
+ [cmwizard menu=main/]
539
  `
540
 
541
  * Show the children of the current menu item within the "main" menu, for unlimited depth, setting the widget title from the current menu item
542
 
543
  `
544
+ [cmwizard menu=main branch=current start_at=children title_from=current/]
545
  `
546
 
547
  * From the "animals" menu, show all the items *immediately* below "Small Dogs", plus "Small Dogs" and its sibling items, as ordered lists
548
 
549
  `
550
+ [cmwizard menu="animals" branch="small dogs" depth=2 include="siblings" ol_root=1 ol_sub=1/]
551
  `
552
 
553
  * From the "animals" menu, show the entire "Small Animals" branch, with the sole exception of the "Small Animals" item itself, whenever "Small Animals" or one of its descendants is the current menu item
554
 
555
  `
556
+ [cmwizard menu="animals" branch="small animals" start_at=children contains_current=primary/]
557
  `
558
 
559
  == Installation ==
652
  post type, id, whether the shortcode(s) are in content and/or meta data, and the shortcode(s) concerned.
653
  This utility does not check things like text widgets, plugin-specific tables, theme-provided textareas, etc.
654
 
655
+ There is also an extension to the shortcode - `[cmwizard findme=1/]` - that will output the same information, should you not be able to use
656
  the "assist" (for some unknown reason). You may optionally provide a title attribute; any other attributes are ignored.
657
  Note that output from this shortcode extension is restricted to users with edit_pages capability.
658
 
669
 
670
  == Changelog ==
671
 
672
+ = 3.0.3 =
673
+ * bugfix : removed all occurrences of "Plugin " followed by "Name" from everywhere except the main plugin file to avoid update() reporting Invalid Header when activating straight from installation (rather than from the Plugins page)
674
+ * tweak : eliminate the over-use of get_title() when determining the widget title
675
+ * tweak : added self-terminating forward slash to generated shortcodes
676
+ * change : prepare for WordPress v4 (avoid use of deprecated functions)
677
+
678
  = 3.0.2 =
679
  * bugfix : the shortcode display on new instances of the widget (in admin) did not initially reflect the automatically-selected menu
680
 
781
 
782
  == Upgrade Notice ==
783
 
784
+ = 3.0.3 =
785
+ Fixed problem with WordPress's update() reporting Invalid Header when activating immediately following installation (as opposed to activating via Plugins page).
786
+ Tweaked the generated shortcode to add a self-terminating forward slash. Please note that this tweak is merely a metter of "good practice" : there is no need to update your existing, working, shortcodes!
787
+ Also removed multiple calls to get_title() when determining the widget's title, and made some minor updates in readiness for WordPress v4.
788
+
789
  = 3.0.2 =
790
  Fixed a bug where the shortcode displayed on new instances of the widget (in admin) did not initially reflect the automatically-selected menu
791