Completed
Pull Request — master (#268)
by
unknown
01:51
created

wp-bootstrap-navwalker.php (4 issues)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
/**
3
 * WP Bootstrap Navwalker
4
 *
5
 * @package WP-Bootstrap-Navwalker
6
 */
7
8
/*
9
 * Class Name: WP_Bootstrap_Navwalker
10
 * Plugin Name: WP Bootstrap Navwalker
11
 * Plugin URI:  https://github.com/wp-bootstrap/wp-bootstrap-navwalker
12
 * Description: A custom WordPress nav walker class to implement the Bootstrap 3 navigation style in a custom theme using the WordPress built in menu manager.
13
 * Author: Edward McIntyre - @twittem, WP Bootstrap
14
 * Version: 2.0.5
15
 * Author URI: https://github.com/wp-bootstrap
16
 * GitHub Plugin URI: https://github.com/wp-bootstrap/wp-bootstrap-navwalker
17
 * GitHub Branch: master
18
 * License: GPL-3.0+
19
 * License URI: http://www.gnu.org/licenses/gpl-3.0.txt
20
*/
21
22
/* Check if Class Exists. */
23
if ( ! class_exists( 'WP_Bootstrap_Navwalker' ) ) {
24
  /**
25
   * WP_Bootstrap_Navwalker class.
26
   *
27
   * @extends Walker_Nav_Menu
28
   */
29
  class WP_Bootstrap_Navwalker extends Walker_Nav_Menu {
0 ignored issues
show
Coding Style Compatibility introduced by
PSR1 recommends that each class must be in a namespace of at least one level to avoid collisions.

You can fix this by adding a namespace to your class:

namespace YourVendor;

class YourClass { }

When choosing a vendor namespace, try to pick something that is not too generic to avoid conflicts with other libraries.

Loading history...
30
31
    /**
32
     * Start Level.
33
     *
34
     * @see Walker::start_lvl()
35
     * @since 3.0.0
36
     *
37
     * @access public
38
     * @param mixed $output Passed by reference. Used to append additional content.
39
     * @param int   $depth (default: 0) Depth of page. Used for padding.
40
     * @param array $args (default: array()) Arguments.
41
     * @return void
42
     */
43
    public function start_lvl( &$output, $depth = 0, $args = array() ) {
44
      $indent = str_repeat( "\t", $depth );
45
      $output .= "\n$indent<ul role=\"menu\" class=\" dropdown-menu\" >\n";
46
    }
47
48
    /**
49
     * Start El.
50
     *
51
     * @see Walker::start_el()
52
     * @since 3.0.0
53
     *
54
     * @access public
55
     * @param mixed $output Passed by reference. Used to append additional content.
56
     * @param mixed $item Menu item data object.
57
     * @param int   $depth (default: 0) Depth of menu item. Used for padding.
58
     * @param array $args (default: array()) Arguments.
59
     * @param int   $id (default: 0) Menu item ID.
60
     * @return void
61
     */
62
    public function start_el( &$output, $item, $depth = 0, $args = array(), $id = 0 ) {
63
      $indent = ( $depth ) ? str_repeat( "\t", $depth ) : '';
64
65
      /**
66
      * Dividers, Headers or Disabled
67
      * =============================
68
      * Determine whether the item is a Divider, Header, Disabled or regular
69
      * menu item. To prevent errors we use the strcasecmp() function to so a
70
      * comparison that is not case sensitive. The strcasecmp() function returns
71
      * a 0 if the strings are equal.
72
      */
73
      if ( 0 === strcasecmp( $item->attr_title, 'divider' ) && 1 === $depth ) {
74
        $output .= $indent . '<li role="presentation" class="divider">';
75
      } elseif ( 0 === strcasecmp( $item->title, 'divider' ) && 1 === $depth ) {
76
        $output .= $indent . '<li role="presentation" class="divider">';
77
      } elseif ( 0 === strcasecmp( $item->attr_title, 'dropdown-header' ) && 1 === $depth ) {
78
        $output .= $indent . '<li role="presentation" class="dropdown-header">' . esc_attr( $item->title );
79
      } elseif ( 0 === strcasecmp( $item->attr_title, 'disabled' ) ) {
80
        $output .= $indent . '<li role="presentation" class="disabled"><a href="#">' . esc_attr( $item->title ) . '</a>';
81
      } else {
82
        $class_names = $value = '';
0 ignored issues
show
$class_names is not used, you could remove the assignment.

This check looks for variable assignements that are either overwritten by other assignments or where the variable is not used subsequently.

$myVar = 'Value';
$higher = false;

if (rand(1, 6) > 3) {
    $higher = true;
} else {
    $higher = false;
}

Both the $myVar assignment in line 1 and the $higher assignment in line 2 are dead. The first because $myVar is never used and the second because $higher is always overwritten for every possible time line.

Loading history...
83
        $classes = empty( $item->classes ) ? array() : (array) $item->classes;
84
        $classes[] = 'menu-item-' . $item->ID;
85
        $class_names = join( ' ', apply_filters( 'nav_menu_css_class', array_filter( $classes ), $item, $args ) );
86
        if ( $args->has_children ) {
87
          $class_names .= ' dropdown'; }
88
        if ( in_array( 'current-menu-item', $classes, true ) ) {
89
          $class_names .= ' active'; }
90
        $class_names = $class_names ? ' class="' . esc_attr( $class_names ) . '"' : '';
91
        $id = apply_filters( 'nav_menu_item_id', 'menu-item-' . $item->ID, $item, $args );
92
        $id = $id ? ' id="' . esc_attr( $id ) . '"' : '';
93
        $output .= $indent . '<li itemscope="itemscope" itemtype="https://www.schema.org/SiteNavigationElement"' . $id . $value . $class_names . '>';
94
        $atts = array();
95
96
        if ( empty( $item->attr_title ) ) {
97
            $atts['title']  = ! empty( $item->title )   ? strip_tags( $item->title ) : '';
98
        } else {
99
            $atts['title'] = $item->attr_title;
100
        }
101
102
        $atts['target'] = ! empty( $item->target )  ? $item->target : '';
103
        $atts['rel']    = ! empty( $item->xfn )   ? $item->xfn  : '';
104
        // If item has_children add atts to a.
105
        if ( $args->has_children && 0 === $depth ) {
106
          $atts['href']       = '#';
107
          $atts['data-toggle']  = 'dropdown';
108
          $atts['class']      = 'dropdown-toggle';
109
          $atts['aria-haspopup']  = 'true';
110
        } else {
111
          $atts['href'] = ! empty( $item->url ) ? $item->url : '';
112
        }
113
        $atts = apply_filters( 'nav_menu_link_attributes', $atts, $item, $args );
114
        $attributes = '';
115
        foreach ( $atts as $attr => $value ) {
116
          if ( ! empty( $value ) ) {
117
            $value = ( 'href' === $attr ) ? esc_url( $value ) : esc_attr( $value );
118
            $attributes .= ' ' . $attr . '="' . $value . '"';
119
          }
120
        }
121
        $item_output = $args->before;
122
123
        /*
124
         * Glyphicons/Font-Awesome
125
         * ===========
126
         * Since the the menu item is NOT a Divider or Header we check the see
127
         * if there is a value in the attr_title property. If the attr_title
128
         * property is NOT null we apply it as the class name for the glyphicon.
129
         */
130
        if ( ! empty( $item->attr_title ) ) :
131
                $pos = strpos( esc_attr( $item->attr_title ), 'glyphicon' );
132
          if ( false !== $pos ) :
133
            $item_output .= '<a' . $attributes . '><span class="glyphicon ' . esc_attr( $item->attr_title ) . '" aria-hidden="true"></span>&nbsp;';
134
                else :
135
                  $item_output .= '<a' . $attributes . '><i class="fa ' . esc_attr( $item->attr_title ) . '" aria-hidden="true"></i>&nbsp;';
136
                      endif;
137
        else :
138
          $item_output .= '<a' . $attributes . '>';
139
        endif;
140
        $item_output .= $args->link_before . apply_filters( 'the_title', $item->title, $item->ID ) . $args->link_after;
141
        $item_output .= ( $args->has_children && 0 === $depth ) ? ' <span class="caret"></span></a>' : '</a>';
142
        $item_output .= $args->after;
143
        $output .= apply_filters( 'walker_nav_menu_start_el', $item_output, $item, $depth, $args );
144
      }
145
    }
146
147
    /**
148
     * Traverse elements to create list from elements.
149
     *
150
     * Display one element if the element doesn't have any children otherwise,
151
     * display the element and its children. Will only traverse up to the max
152
     * depth and no ignore elements under that depth.
153
     *
154
     * This method shouldn't be called directly, use the walk() method instead.
155
     *
156
     * @see Walker::start_el()
157
     * @since 2.5.0
158
     *
159
     * @access public
160
     * @param mixed $element Data object.
161
     * @param mixed $children_elements List of elements to continue traversing.
162
     * @param mixed $max_depth Max depth to traverse.
163
     * @param mixed $depth Depth of current element.
164
     * @param mixed $args Arguments.
165
     * @param mixed $output Passed by reference. Used to append additional content.
166
     * @return null Null on failure with no changes to parameters.
167
     */
168
    public function display_element( $element, &$children_elements, $max_depth, $depth, $args, &$output ) {
169
      if ( ! $element ) {
170
        return; }
171
      $id_field = $this->db_fields['id'];
172
      // Display this element.
173
      if ( is_object( $args[0] ) ) {
174
        $args[0]->has_children = ! empty( $children_elements[ $element->$id_field ] ); }
175
      parent::display_element( $element, $children_elements, $max_depth, $depth, $args, $output );
176
    }
177
178
    /**
179
     * Menu Fallback
180
     * =============
181
     * If this function is assigned to the wp_nav_menu's fallback_cb variable
182
     * and a menu has not been assigned to the theme location in the WordPress
183
     * menu manager the function with display nothing to a non-logged in user,
184
     * and will add a link to the WordPress menu manager if logged in as an admin.
185
     *
186
     * @param array $args passed from the wp_nav_menu function.
187
     */
188
    public static function fallback( $args ) {
189
      if ( current_user_can( 'edit_theme_options' ) ) {
190
191
        /* Get Arguments. */
192
        $container = $args['container'];
193
        $container_id = $args['container_id'];
194
        $container_class = $args['container_class'];
195
        $menu_class = $args['menu_class'];
196
        $menu_id = $args['menu_id'];
197
198
        $fb_output_safe = '';
199
        
200
        if ( $container ) {
201
          $fb_output_safe .= '<' . esc_attr( $container );
202
          if ( $container_id ) {
203
            $fb_output_safe .= ' id="' . esc_attr( $container_id ) . '"';
204
          }
205
          if ( $container_class ) {
206
            $fb_output_safe .= ' class="' . sanitize_html_class( $container_class ) . '"'; }
207
          $fb_output_safe .= '>';
208
        }
209
        $fb_output_safe .= '<ul';
210
        if ( $menu_id ) {
211
          $fb_output_safe .= ' id="' . esc_attr( $menu_id ) . '"'; }
212
        if ( $menu_class ) {
213
          $fb_output_safe .= ' class="' . esc_attr( $menu_class ) . '"'; }
214
        $fb_output_safe .= '>';
215
        $fb_output_safe .= '<li><a href="' . esc_url( admin_url( 'nav-menus.php' ) ) . '" title="">' . esc_attr( 'Add a menu', '' ) . '</a></li>';
216
        $fb_output_safe .= '</ul>';
217
        if ( $container ) {
218
          $fb_output_safe .= '</' . esc_attr( $container ) . '>'; }
219
      }
220
      
221
      // if echo, echo, otherwise return
0 ignored issues
show
Unused Code Comprehensibility introduced by
50% of this comment could be valid code. Did you maybe forget this after debugging?

Sometimes obsolete code just ends up commented out instead of removed. In this case it is better to remove the code once you have checked you do not need it.

The code might also have been commented out for debugging purposes. In this case it is vital that someone uncomments it again or your project may behave in very unexpected ways in production.

This check looks for comments that seem to be mostly valid code and reports them.

Loading history...
222
      if ( $args['echo'] ):
223
        echo $fb_output_safe;
0 ignored issues
show
The variable $fb_output_safe does not seem to be defined for all execution paths leading up to this point.

If you define a variable conditionally, it can happen that it is not defined for all execution paths.

Let’s take a look at an example:

function myFunction($a) {
    switch ($a) {
        case 'foo':
            $x = 1;
            break;

        case 'bar':
            $x = 2;
            break;
    }

    // $x is potentially undefined here.
    echo $x;
}

In the above example, the variable $x is defined if you pass “foo” or “bar” as argument for $a. However, since the switch statement has no default case statement, if you pass any other value, the variable $x would be undefined.

Available Fixes

  1. Check for existence of the variable explicitly:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        if (isset($x)) { // Make sure it's always set.
            echo $x;
        }
    }
    
  2. Define a default value for the variable:

    function myFunction($a) {
        $x = ''; // Set a default which gets overridden for certain paths.
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
        }
    
        echo $x;
    }
    
  3. Add a value for the missing path:

    function myFunction($a) {
        switch ($a) {
            case 'foo':
                $x = 1;
                break;
    
            case 'bar':
                $x = 2;
                break;
    
            // We add support for the missing case.
            default:
                $x = '';
                break;
        }
    
        echo $x;
    }
    
Loading history...
224
      else:
225
        return $fb_output_safe;
226
      endif;   
227
228
229
    }
230
  }
231
}
232