From 5ed53d6479485c0714c1e6f6ae898c479851316b Mon Sep 17 00:00:00 2001 From: IanDelMar <42134098+IanDelMar@users.noreply.github.com> Date: Mon, 8 Nov 2021 21:59:23 +0100 Subject: [PATCH 01/10] Fix placement of .active class for dropdown items --- class-wp-bootstrap-navwalker.php | 32 +++++++++++++++++++++++++++++--- 1 file changed, 29 insertions(+), 3 deletions(-) diff --git a/class-wp-bootstrap-navwalker.php b/class-wp-bootstrap-navwalker.php index 9b0d424..b836aa0 100644 --- a/class-wp-bootstrap-navwalker.php +++ b/class-wp-bootstrap-navwalker.php @@ -152,6 +152,30 @@ public function start_el( &$output, $item, $depth = 0, $args = null, $id = 0 ) { // Join any icon classes plucked from $classes into a string. $icon_class_string = join( ' ', $icon_classes ); + // Whether the current item is a dropdown. + $is_dropdown = false; + if ( $this->has_children && 1 !== $args->depth ) { + $is_dropdown = true; + if ( $depth >= $args->depth - 1 && $args->depth !== 0 ) { + $is_dropdown = false; + } + } + + // Whether the current item is a dropdown item. + $is_dropdown_item = false; + if ( ! ( $this->has_children && 0 === $depth ) && $depth > 0 ) { + $is_dropdown_item = true; + } + + // Whether the current item is active or the item is an ancestor of + // the current item. + $is_active = false; + if ( $item->current || $item->current_item_ancestor ) { + if ( ! ( $item->current_item_ancestor && 1 === $args->depth ) ) { + $is_active = true; + } + } + /** * Filters the arguments for a single nav menu item. * @@ -165,11 +189,12 @@ public function start_el( &$output, $item, $depth = 0, $args = null, $id = 0 ) { */ $args = apply_filters( 'nav_menu_item_args', $args, $item, $depth ); - // Add .dropdown or .active classes where they are needed. - if ( $this->has_children ) { + if ( $is_dropdown ) { $classes[] = 'dropdown'; } - if ( in_array( 'current-menu-item', $classes, true ) || in_array( 'current-menu-parent', $classes, true ) ) { + + if ( $is_active && ! $is_dropdown_item ) { + // For dropdown items the .active class is set on the a tag. $classes[] = 'active'; } @@ -226,6 +251,7 @@ public function start_el( &$output, $item, $depth = 0, $args = null, $id = 0 ) { // For items in dropdowns use .dropdown-item instead of .nav-link. if ( $depth > 0 ) { $atts['class'] = 'dropdown-item'; + $atts['class'] .= $is_active ? ' active' : ''; } else { $atts['class'] = 'nav-link'; } From a19dba8b4a7c20637cc4ece1bfbb1a1b4e2fd8b0 Mon Sep 17 00:00:00 2001 From: IanDelMar <42134098+IanDelMar@users.noreply.github.com> Date: Mon, 8 Nov 2021 22:03:17 +0100 Subject: [PATCH 02/10] Fix dropdown being set when children are not displayed --- class-wp-bootstrap-navwalker.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/class-wp-bootstrap-navwalker.php b/class-wp-bootstrap-navwalker.php index b836aa0..1156d1f 100644 --- a/class-wp-bootstrap-navwalker.php +++ b/class-wp-bootstrap-navwalker.php @@ -236,7 +236,7 @@ public function start_el( &$output, $item, $depth = 0, $args = null, $id = 0 ) { } // If the item has_children add atts to . - if ( $this->has_children && 0 === $depth ) { + if ( $is_dropdown ) { $atts['href'] = '#'; $atts['data-toggle'] = 'dropdown'; $atts['aria-expanded'] = 'false'; From a369503b6b3cc8005f42c5eae0708af38c8aa8f9 Mon Sep 17 00:00:00 2001 From: IanDelMar <42134098+IanDelMar@users.noreply.github.com> Date: Mon, 8 Nov 2021 23:00:05 +0100 Subject: [PATCH 03/10] Use $is_dropdown_item --- class-wp-bootstrap-navwalker.php | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/class-wp-bootstrap-navwalker.php b/class-wp-bootstrap-navwalker.php index 1156d1f..679b3c4 100644 --- a/class-wp-bootstrap-navwalker.php +++ b/class-wp-bootstrap-navwalker.php @@ -248,8 +248,9 @@ public function start_el( &$output, $item, $depth = 0, $args = null, $id = 0 ) { } $atts['href'] = ! empty( $item->url ) ? $item->url : '#'; + // For items in dropdowns use .dropdown-item instead of .nav-link. - if ( $depth > 0 ) { + if ( $is_dropdown_item ) { $atts['class'] = 'dropdown-item'; $atts['class'] .= $is_active ? ' active' : ''; } else { From 979e3a0d16f575fd577bea79c2c4063ed8aa38ca Mon Sep 17 00:00:00 2001 From: IanDelMar <42134098+IanDelMar@users.noreply.github.com> Date: Mon, 8 Nov 2021 23:00:29 +0100 Subject: [PATCH 04/10] Fix wpcs --- class-wp-bootstrap-navwalker.php | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/class-wp-bootstrap-navwalker.php b/class-wp-bootstrap-navwalker.php index 679b3c4..8165399 100644 --- a/class-wp-bootstrap-navwalker.php +++ b/class-wp-bootstrap-navwalker.php @@ -156,7 +156,7 @@ public function start_el( &$output, $item, $depth = 0, $args = null, $id = 0 ) { $is_dropdown = false; if ( $this->has_children && 1 !== $args->depth ) { $is_dropdown = true; - if ( $depth >= $args->depth - 1 && $args->depth !== 0 ) { + if ( $depth >= $args->depth - 1 && 0 !== $args->depth ) { $is_dropdown = false; } } @@ -251,7 +251,7 @@ public function start_el( &$output, $item, $depth = 0, $args = null, $id = 0 ) { // For items in dropdowns use .dropdown-item instead of .nav-link. if ( $is_dropdown_item ) { - $atts['class'] = 'dropdown-item'; + $atts['class'] = 'dropdown-item'; $atts['class'] .= $is_active ? ' active' : ''; } else { $atts['class'] = 'nav-link'; From e6f21f80d3db6e55607d42dcaa85843d80cc3cff Mon Sep 17 00:00:00 2001 From: IanDelMar <42134098+IanDelMar@users.noreply.github.com> Date: Tue, 9 Nov 2021 06:16:09 +0100 Subject: [PATCH 05/10] Fix variable description --- class-wp-bootstrap-navwalker.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/class-wp-bootstrap-navwalker.php b/class-wp-bootstrap-navwalker.php index 8165399..53c9978 100644 --- a/class-wp-bootstrap-navwalker.php +++ b/class-wp-bootstrap-navwalker.php @@ -168,7 +168,7 @@ public function start_el( &$output, $item, $depth = 0, $args = null, $id = 0 ) { } // Whether the current item is active or the item is an ancestor of - // the current item. + // an active item. $is_active = false; if ( $item->current || $item->current_item_ancestor ) { if ( ! ( $item->current_item_ancestor && 1 === $args->depth ) ) { From 20c07e1fb36d83288a8bc0674714d599e2e61b37 Mon Sep 17 00:00:00 2001 From: IanDelMar <42134098+IanDelMar@users.noreply.github.com> Date: Tue, 9 Nov 2021 07:59:10 +0100 Subject: [PATCH 06/10] Add Bootstrap 5 support --- class-wp-bootstrap-navwalker.php | 130 +++++++++++++++++++------------ 1 file changed, 80 insertions(+), 50 deletions(-) diff --git a/class-wp-bootstrap-navwalker.php b/class-wp-bootstrap-navwalker.php index 53c9978..3e3c08a 100644 --- a/class-wp-bootstrap-navwalker.php +++ b/class-wp-bootstrap-navwalker.php @@ -33,7 +33,14 @@ class WP_Bootstrap_Navwalker extends Walker_Nav_Menu { private $has_schema = false; /** - * Ensure the items_wrap argument contains microdata. + * The default major Bootstrap version for which to create the markup. + * + * @var int + */ + private $bs_version = 4; + + /** + * Ensures the items_wrap argument contains microdata. * * @since 4.2.0 */ @@ -52,7 +59,7 @@ public function __construct() { * * @param string $output Used to append additional content (passed by reference). * @param int $depth Depth of menu item. Used for padding. - * @param WP_Nav_Menu_Args $args An object of wp_nav_menu() arguments. + * @param WP_Nav_Menu_Args $args An object of `wp_nav_menu()` arguments. */ public function start_lvl( &$output, $depth = 0, $args = null ) { if ( isset( $args->item_spacing ) && 'discard' === $args->item_spacing ) { @@ -63,8 +70,10 @@ public function start_lvl( &$output, $depth = 0, $args = null ) { $n = "\n"; } $indent = str_repeat( $t, $depth ); - // Default class to add to the file. + + // Default class to add to the start of the list (usually ul tag). $classes = array( 'dropdown-menu' ); + /** * Filters the CSS class(es) applied to a menu list element. * @@ -106,7 +115,7 @@ public function start_lvl( &$output, $depth = 0, $args = null ) { * @param string $output Used to append additional content (passed by reference). * @param WP_Nav_Menu_Item $item Menu item data object. * @param int $depth Depth of menu item. Used for padding. - * @param WP_Nav_Menu_Args $args An object of wp_nav_menu() arguments. + * @param WP_Nav_Menu_Args $args An object of `wp_nav_menu()` arguments. * @param int $id Current item ID. */ public function start_el( &$output, $item, $depth = 0, $args = null, $id = 0 ) { @@ -127,8 +136,11 @@ public function start_el( &$output, $item, $depth = 0, $args = null, $id = 0 ) { $classes = empty( $item->classes ) ? array() : (array) $item->classes; - // Updating the CSS classes of a menu item in the WordPress Customizer preview results in all classes defined - // in that particular input box to come in as one big class string. + /* + * Updating the CSS classes of a menu item in the WordPress + * Customizer preview results in all classes defined in that + * particular input box to come in as one big class string. + */ $split_on_spaces = function ( $class ) { return preg_split( '/\s+/', $class ); }; @@ -152,6 +164,9 @@ public function start_el( &$output, $item, $depth = 0, $args = null, $id = 0 ) { // Join any icon classes plucked from $classes into a string. $icon_class_string = join( ' ', $icon_classes ); + // Bootstrap version to create the markup for. + $bs_version = $this->get_bs_version( $args ); + // Whether the current item is a dropdown. $is_dropdown = false; if ( $this->has_children && 1 !== $args->depth ) { @@ -167,8 +182,10 @@ public function start_el( &$output, $item, $depth = 0, $args = null, $id = 0 ) { $is_dropdown_item = true; } - // Whether the current item is active or the item is an ancestor of - // an active item. + /* + * Whether the current item is active or the item is an ancestor of + * an active item. + */ $is_active = false; if ( $item->current || $item->current_item_ancestor ) { if ( ! ( $item->current_item_ancestor && 1 === $args->depth ) ) { @@ -181,7 +198,7 @@ public function start_el( &$output, $item, $depth = 0, $args = null, $id = 0 ) { * * @since WP 4.4.0 * - * @param WP_Nav_Menu_Args $args An object of wp_nav_menu() arguments. + * @param WP_Nav_Menu_Args $args An object of `wp_nav_menu()` arguments. * @param WP_Nav_Menu_Item $item Menu item data object. * @param int $depth Depth of menu item. Used for padding. * @@ -193,7 +210,7 @@ public function start_el( &$output, $item, $depth = 0, $args = null, $id = 0 ) { $classes[] = 'dropdown'; } - if ( $is_active && ! $is_dropdown_item ) { + if ( $is_active && ! $is_dropdown_item && 5 !== $bs_version ) { // For dropdown items the .active class is set on the a tag. $classes[] = 'active'; } @@ -217,7 +234,7 @@ public function start_el( &$output, $item, $depth = 0, $args = null, $id = 0 ) { * * @param string $menu_id The ID that is applied to the menu item's `
  • ` element. * @param WP_Nav_Menu_Item $item The current menu item. - * @param WP_Nav_Menu_Args $args An object of wp_nav_menu() arguments. + * @param WP_Nav_Menu_Args $args An object of `wp_nav_menu()` arguments. * @param int $depth Depth of menu item. Used for padding. */ $id = apply_filters( 'nav_menu_item_id', 'menu-item-' . $item->ID, $item, $args, $depth ); @@ -237,11 +254,18 @@ public function start_el( &$output, $item, $depth = 0, $args = null, $id = 0 ) { // If the item has_children add atts to . if ( $is_dropdown ) { - $atts['href'] = '#'; - $atts['data-toggle'] = 'dropdown'; - $atts['aria-expanded'] = 'false'; - $atts['class'] = 'dropdown-toggle nav-link'; - $atts['id'] = 'menu-item-dropdown-' . $item->ID; + $infix = ''; + if ( 5 === $this->get_bs_version( $args ) ) { + $infix = '-bs'; + } + + $atts['href'] = '#'; + $atts["data$infix-toggle"] = 'dropdown'; + $atts['aria-expanded'] = 'false'; + $atts['class'] = 'dropdown-toggle nav-link'; + $atts['id'] = 'menu-item-dropdown-' . $item->ID; + + $atts['class'] .= ( $is_active && 5 === $bs_version ) ? ' active' : ''; } else { if ( true === $this->has_schema ) { $atts['itemprop'] = 'url'; @@ -314,7 +338,7 @@ public function start_el( &$output, $item, $depth = 0, $args = null, $id = 0 ) { * * @param string $title The menu item's title. * @param WP_Nav_Menu_Item $item The current menu item. - * @param WP_Nav_Menu_Args $args An object of wp_nav_menu() arguments. + * @param WP_Nav_Menu_Args $args An object of `wp_nav_menu()` arguments. * @param int $depth Depth of menu item. Used for padding. */ $title = apply_filters( 'nav_menu_item_title', $title, $item, $args, $depth ); @@ -357,7 +381,7 @@ public function start_el( &$output, $item, $depth = 0, $args = null, $id = 0 ) { * menu manager the function will display nothing to a non-logged in user, * and will add a link to the WordPress menu manager if logged in as an admin. * - * @param array $args passed from the wp_nav_menu function. + * @param array $args Arguments passed from the `wp_nav_menu()` function. * @return string|void String when echo is false. */ public static function fallback( $args ) { @@ -400,7 +424,7 @@ public static function fallback( $args ) { $fallback_output .= ''; } - // if $args has 'echo' key and it's true echo, otherwise return. + // If $args has 'echo' key and it's true echo, otherwise return. if ( array_key_exists( 'echo', $args ) && $args['echo'] ) { // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped echo $fallback_output; @@ -410,7 +434,7 @@ public static function fallback( $args ) { } /** - * Filter to ensure the items_Wrap argument contains microdata. + * Filter to ensure the items_wrap argument contains microdata. * * @since 4.2.0 * @@ -428,7 +452,7 @@ public function add_schema_to_navbar_ul( $args ) { } /** - * Find any custom linkmod or icon classes and store in their holder + * Finds any custom linkmod or icon classes and store in their holder * arrays then remove them from the main classes array. * * Supported linkmods: .disabled, .dropdown-header, .dropdown-divider, .sr-only @@ -438,12 +462,11 @@ public function add_schema_to_navbar_ul( $args ) { * * @since 4.0.0 * - * @param array $classes an array of classes currently assigned to the item. - * @param array $linkmod_classes an array to hold linkmod classes. - * @param array $icon_classes an array to hold icon classes. - * @param integer $depth an integer holding current depth level. - * - * @return array $classes a maybe modified array of classnames. + * @param array $classes An array of classes currently assigned to the item. + * @param array $linkmod_classes An array to hold linkmod classes. + * @param array $icon_classes An array to hold icon classes. + * @param integer $depth An integer holding current depth level. + * @return array $classes A maybe modified array of classnames. */ private function separate_linkmods_and_icons_from_classes( $classes, &$linkmod_classes, &$icon_classes, $depth ) { // Loop through $classes array to find linkmod or icon classes. @@ -478,14 +501,13 @@ private function separate_linkmods_and_icons_from_classes( $classes, &$linkmod_c } /** - * Return a string containing a linkmod type and update $atts array - * accordingly depending on the decided. + * Returns a string containing a linkmod type and updates the $atts + * array accordingly depending on the decided. * * @since 4.0.0 * - * @param array $linkmod_classes array of any link modifier classes. - * - * @return string empty for default, a linkmod type string otherwise. + * @param array $linkmod_classes Array of any link modifier classes. + * @return string Empty for default, a linkmod type string otherwise. */ private function get_linkmod_type( $linkmod_classes = array() ) { $linkmod_type = ''; @@ -509,14 +531,13 @@ private function get_linkmod_type( $linkmod_classes = array() ) { } /** - * Update the attributes of a nav item depending on the limkmod classes. + * Updates the attributes of a nav item depending on the limkmod classes. * * @since 4.0.0 * - * @param array $atts array of atts for the current link in nav item. - * @param array $linkmod_classes an array of classes that modify link or nav item behaviors or displays. - * - * @return array maybe updated array of attributes for item. + * @param array $atts Array of atts for the current link in nav item. + * @param array $linkmod_classes An array of classes that modify link or nav item behaviors or displays. + * @return array Maybe updated array of attributes for item. */ private function update_atts_for_linkmod_type( $atts = array(), $linkmod_classes = array() ) { if ( ! empty( $linkmod_classes ) ) { @@ -550,8 +571,8 @@ private function update_atts_for_linkmod_type( $atts = array(), $linkmod_classes * * @since 4.0.0 * - * @param string $text the string of text to be wrapped in a screen reader class. - * @return string the string wrapped in a span with the class. + * @param string $text The string of text to be wrapped in a screen reader class. + * @return string The string wrapped in a span with the class. */ private function wrap_for_screen_reader( $text = '' ) { if ( $text ) { @@ -565,10 +586,9 @@ private function wrap_for_screen_reader( $text = '' ) { * * @since 4.0.0 * - * @param string $linkmod_type a sting containing a linkmod type flag. - * @param string $attributes a string of attributes to add to the element. - * - * @return string a string with the openign tag for the element with attribibutes added. + * @param string $linkmod_type A string containing a linkmod type flag. + * @param string $attributes A string of attributes to add to the element. + * @return string A string with the opening tag for the element with attribibutes added. */ private function linkmod_element_open( $linkmod_type, $attributes = '' ) { $output = ''; @@ -588,13 +608,12 @@ private function linkmod_element_open( $linkmod_type, $attributes = '' ) { } /** - * Return the correct closing tag for the linkmod element. + * Returns the correct closing tag for the linkmod element. * * @since 4.0.0 * - * @param string $linkmod_type a string containing a special linkmod type. - * - * @return string a string with the closing tag for this linkmod type. + * @param string $linkmod_type A string containing a special linkmod type. + * @return string A string with the closing tag for this linkmod type. */ private function linkmod_element_close( $linkmod_type ) { $output = ''; @@ -614,9 +633,8 @@ private function linkmod_element_close( $linkmod_type ) { /** * Flattens a multidimensional array to a simple array. * - * @param array $array a multidimensional array. - * - * @return array a simple array + * @param array $array A multidimensional array. + * @return array A simple array. */ public function flatten( $array ) { $result = array(); @@ -630,6 +648,18 @@ public function flatten( $array ) { return $result; } + /** + * Retrieves the Bootstrap version to use. + * + * @param WP_Nav_Menu_Args $args An object of `wp_nav_menu()` arguments. + * @return int Major Bootstrap version + */ + private function get_bs_version( $args ) { + if ( property_exists( $args, 'bs_version' ) && 5 === (int) $args->bs_version ) { + return (int) $args->bs_version; + } + return $this->bs_version; + } } endif; From d9ed8a4b1b32285681d4f90a3a5345b3925c7654 Mon Sep 17 00:00:00 2001 From: IanDelMar <42134098+IanDelMar@users.noreply.github.com> Date: Tue, 9 Nov 2021 08:01:07 +0100 Subject: [PATCH 07/10] Update instructions for usage with Bootstrap 5 --- README.md | 33 +++++++++++++-------------------- 1 file changed, 13 insertions(+), 20 deletions(-) diff --git a/README.md b/README.md index 92743eb..d5f1ba6 100644 --- a/README.md +++ b/README.md @@ -146,27 +146,20 @@ Bootstrap 5 uses namespaced data attributes. All `data` attributes now include ` ``` -The walker also adds a data attribute for dropdown toggles via the `start_el()` method. Paste this to your functions.php to make the walker use the infixed data attibute. +To enable Bootstrap 5 support add a `bs_version` key to the array of arguments passed to the `wp_nav_menu()` function. -```php -add_filter( 'nav_menu_link_attributes', 'prefix_bs5_dropdown_data_attribute', 20, 3 ); -/** - * Use namespaced data attribute for Bootstrap's dropdown toggles. - * - * @param array $atts HTML attributes applied to the item's `` element. - * @param WP_Post $item The current menu item. - * @param stdClass $args An object of wp_nav_menu() arguments. - * @return array - */ -function prefix_bs5_dropdown_data_attribute( $atts, $item, $args ) { - if ( is_a( $args->walker, 'WP_Bootstrap_Navwalker' ) ) { - if ( array_key_exists( 'data-toggle', $atts ) ) { - unset( $atts['data-toggle'] ); - $atts['data-bs-toggle'] = 'dropdown'; - } - } - return $atts; -} +```diff +wp_nav_menu( array( + 'theme_location' => 'primary', + 'depth' => 2, // 1 = no dropdowns, 2 = with dropdowns. + 'container' => 'div', + 'container_class' => 'collapse navbar-collapse', + 'container_id' => 'bs-example-navbar-collapse-1', + 'menu_class' => 'navbar-nav mr-auto', + 'fallback_cb' => 'WP_Bootstrap_Navwalker::fallback', + 'walker' => new WP_Bootstrap_Navwalker(), ++ 'bs_version' => 5, +) ); ``` ### Menu Caching From b0cf2be1a504542184d861f0b296d40ce2ee0261 Mon Sep 17 00:00:00 2001 From: IanDelMar <42134098+IanDelMar@users.noreply.github.com> Date: Tue, 9 Nov 2021 08:03:47 +0100 Subject: [PATCH 08/10] Fix wpcs --- class-wp-bootstrap-navwalker.php | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/class-wp-bootstrap-navwalker.php b/class-wp-bootstrap-navwalker.php index 3e3c08a..0e448ce 100644 --- a/class-wp-bootstrap-navwalker.php +++ b/class-wp-bootstrap-navwalker.php @@ -259,11 +259,11 @@ public function start_el( &$output, $item, $depth = 0, $args = null, $id = 0 ) { $infix = '-bs'; } - $atts['href'] = '#'; - $atts["data$infix-toggle"] = 'dropdown'; - $atts['aria-expanded'] = 'false'; - $atts['class'] = 'dropdown-toggle nav-link'; - $atts['id'] = 'menu-item-dropdown-' . $item->ID; + $atts['href'] = '#'; + $atts[ "data$infix-toggle" ] = 'dropdown'; + $atts['aria-expanded'] = 'false'; + $atts['class'] = 'dropdown-toggle nav-link'; + $atts['id'] = 'menu-item-dropdown-' . $item->ID; $atts['class'] .= ( $is_active && 5 === $bs_version ) ? ' active' : ''; } else { From a03a0c6d92cf142ff643d9bac299c109a3c62a65 Mon Sep 17 00:00:00 2001 From: IanDelMar <42134098+IanDelMar@users.noreply.github.com> Date: Fri, 12 Nov 2021 07:07:01 +0100 Subject: [PATCH 09/10] Reduce complexity by changing class check logic --- class-wp-bootstrap-navwalker.php | 1107 +++++++++++++++--------------- 1 file changed, 554 insertions(+), 553 deletions(-) diff --git a/class-wp-bootstrap-navwalker.php b/class-wp-bootstrap-navwalker.php index 0e448ce..d659b4b 100644 --- a/class-wp-bootstrap-navwalker.php +++ b/class-wp-bootstrap-navwalker.php @@ -18,648 +18,649 @@ */ // Check if Class Exists. -if ( ! class_exists( 'WP_Bootstrap_Navwalker' ) ) : +if ( class_exists( 'WP_Bootstrap_Navwalker' ) ) { + return; +} + +/** + * WP_Bootstrap_Navwalker class. + */ +class WP_Bootstrap_Navwalker extends Walker_Nav_Menu { + /** - * WP_Bootstrap_Navwalker class. + * Whether the items_wrap contains schema microdata or not. + * + * @since 4.2.0 + * @var boolean */ - class WP_Bootstrap_Navwalker extends Walker_Nav_Menu { + private $has_schema = false; - /** - * Whether the items_wrap contains schema microdata or not. - * - * @since 4.2.0 - * @var boolean - */ - private $has_schema = false; + /** + * The default major Bootstrap version for which to create the markup. + * + * @var int + */ + private $bs_version = 4; - /** - * The default major Bootstrap version for which to create the markup. - * - * @var int - */ - private $bs_version = 4; + /** + * Ensures the items_wrap argument contains microdata. + * + * @since 4.2.0 + */ + public function __construct() { + if ( ! has_filter( 'wp_nav_menu_args', array( $this, 'add_schema_to_navbar_ul' ) ) ) { + add_filter( 'wp_nav_menu_args', array( $this, 'add_schema_to_navbar_ul' ) ); + } + } - /** - * Ensures the items_wrap argument contains microdata. - * - * @since 4.2.0 - */ - public function __construct() { - if ( ! has_filter( 'wp_nav_menu_args', array( $this, 'add_schema_to_navbar_ul' ) ) ) { - add_filter( 'wp_nav_menu_args', array( $this, 'add_schema_to_navbar_ul' ) ); - } + /** + * Starts the list before the elements are added. + * + * @since WP 3.0.0 + * + * @see Walker_Nav_Menu::start_lvl() + * + * @param string $output Used to append additional content (passed by reference). + * @param int $depth Depth of menu item. Used for padding. + * @param WP_Nav_Menu_Args $args An object of `wp_nav_menu()` arguments. + */ + public function start_lvl( &$output, $depth = 0, $args = null ) { + if ( isset( $args->item_spacing ) && 'discard' === $args->item_spacing ) { + $t = ''; + $n = ''; + } else { + $t = "\t"; + $n = "\n"; } + $indent = str_repeat( $t, $depth ); + + // Default class to add to the start of the list (usually ul tag). + $classes = array( 'dropdown-menu' ); /** - * Starts the list before the elements are added. - * - * @since WP 3.0.0 + * Filters the CSS class(es) applied to a menu list element. * - * @see Walker_Nav_Menu::start_lvl() + * @since WP 4.8.0 * - * @param string $output Used to append additional content (passed by reference). - * @param int $depth Depth of menu item. Used for padding. - * @param WP_Nav_Menu_Args $args An object of `wp_nav_menu()` arguments. + * @param array $classes The CSS classes that are applied to the menu `'; - - // Menu container closing tag. - if ( $show_container ) { - $fallback_output .= ''; - } + // Menu container closing tag. + if ( $show_container ) { + $fallback_output .= ''; + } - // If $args has 'echo' key and it's true echo, otherwise return. - if ( array_key_exists( 'echo', $args ) && $args['echo'] ) { - // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped - echo $fallback_output; - } else { - return $fallback_output; - } + // If $args has 'echo' key and it's true echo, otherwise return. + if ( array_key_exists( 'echo', $args ) && $args['echo'] ) { + // phpcs:ignore WordPress.Security.EscapeOutput.OutputNotEscaped + echo $fallback_output; + } else { + return $fallback_output; } + } - /** - * Filter to ensure the items_wrap argument contains microdata. - * - * @since 4.2.0 - * - * @param array $args The nav instance arguments. - * @return array $args The altered nav instance arguments. - */ - public function add_schema_to_navbar_ul( $args ) { - if ( isset( $args['items_wrap'] ) ) { - $wrap = $args['items_wrap']; - if ( strpos( $wrap, 'SiteNavigationElement' ) === false ) { - $args['items_wrap'] = preg_replace( '/(>).*>?\%3\$s/', ' itemscope itemtype="http://www.schema.org/SiteNavigationElement"$0', $wrap ); - } + /** + * Filter to ensure the items_wrap argument contains microdata. + * + * @since 4.2.0 + * + * @param array $args The nav instance arguments. + * @return array $args The altered nav instance arguments. + */ + public function add_schema_to_navbar_ul( $args ) { + if ( isset( $args['items_wrap'] ) ) { + $wrap = $args['items_wrap']; + if ( strpos( $wrap, 'SiteNavigationElement' ) === false ) { + $args['items_wrap'] = preg_replace( '/(>).*>?\%3\$s/', ' itemscope itemtype="http://www.schema.org/SiteNavigationElement"$0', $wrap ); } - return $args; } + return $args; + } - /** - * Finds any custom linkmod or icon classes and store in their holder - * arrays then remove them from the main classes array. - * - * Supported linkmods: .disabled, .dropdown-header, .dropdown-divider, .sr-only - * Supported iconsets: Font Awesome 4/5, Glypicons - * - * NOTE: This accepts the linkmod and icon arrays by reference. - * - * @since 4.0.0 - * - * @param array $classes An array of classes currently assigned to the item. - * @param array $linkmod_classes An array to hold linkmod classes. - * @param array $icon_classes An array to hold icon classes. - * @param integer $depth An integer holding current depth level. - * @return array $classes A maybe modified array of classnames. - */ - private function separate_linkmods_and_icons_from_classes( $classes, &$linkmod_classes, &$icon_classes, $depth ) { - // Loop through $classes array to find linkmod or icon classes. - foreach ( $classes as $key => $class ) { + /** + * Finds any custom linkmod or icon classes and store in their holder + * arrays then remove them from the main classes array. + * + * Supported linkmods: .disabled, .dropdown-header, .dropdown-divider, .sr-only + * Supported iconsets: Font Awesome 4/5, Glypicons + * + * NOTE: This accepts the linkmod and icon arrays by reference. + * + * @since 4.0.0 + * + * @param array $classes An array of classes currently assigned to the item. + * @param array $linkmod_classes An array to hold linkmod classes. + * @param array $icon_classes An array to hold icon classes. + * @param integer $depth An integer holding current depth level. + * @return array $classes A maybe modified array of classnames. + */ + private function separate_linkmods_and_icons_from_classes( $classes, &$linkmod_classes, &$icon_classes, $depth ) { + // Loop through $classes array to find linkmod or icon classes. + foreach ( $classes as $key => $class ) { + /* + * If any special classes are found, store the class in it's + * holder array and and unset the item from $classes. + */ + if ( preg_match( '/^disabled|^sr-only/i', $class ) ) { + // Test for .disabled or .sr-only classes. + $linkmod_classes[] = $class; + unset( $classes[ $key ] ); + } elseif ( preg_match( '/^dropdown-header|^dropdown-divider|^dropdown-item-text/i', $class ) && $depth > 0 ) { /* - * If any special classes are found, store the class in it's - * holder array and and unset the item from $classes. - */ - if ( preg_match( '/^disabled|^sr-only/i', $class ) ) { - // Test for .disabled or .sr-only classes. - $linkmod_classes[] = $class; - unset( $classes[ $key ] ); - } elseif ( preg_match( '/^dropdown-header|^dropdown-divider|^dropdown-item-text/i', $class ) && $depth > 0 ) { - /* - * Test for .dropdown-header or .dropdown-divider and a - * depth greater than 0 - IE inside a dropdown. - */ - $linkmod_classes[] = $class; - unset( $classes[ $key ] ); - } elseif ( preg_match( '/^fa-(\S*)?|^fa(s|r|l|b)?(\s?)?$/i', $class ) ) { - // Font Awesome. - $icon_classes[] = $class; - unset( $classes[ $key ] ); - } elseif ( preg_match( '/^glyphicon-(\S*)?|^glyphicon(\s?)$/i', $class ) ) { - // Glyphicons. - $icon_classes[] = $class; - unset( $classes[ $key ] ); - } + * Test for .dropdown-header or .dropdown-divider and a + * depth greater than 0 - IE inside a dropdown. + */ + $linkmod_classes[] = $class; + unset( $classes[ $key ] ); + } elseif ( preg_match( '/^fa-(\S*)?|^fa(s|r|l|b)?(\s?)?$/i', $class ) ) { + // Font Awesome. + $icon_classes[] = $class; + unset( $classes[ $key ] ); + } elseif ( preg_match( '/^glyphicon-(\S*)?|^glyphicon(\s?)$/i', $class ) ) { + // Glyphicons. + $icon_classes[] = $class; + unset( $classes[ $key ] ); } - - return $classes; } - /** - * Returns a string containing a linkmod type and updates the $atts - * array accordingly depending on the decided. - * - * @since 4.0.0 - * - * @param array $linkmod_classes Array of any link modifier classes. - * @return string Empty for default, a linkmod type string otherwise. - */ - private function get_linkmod_type( $linkmod_classes = array() ) { - $linkmod_type = ''; - // Loop through array of linkmod classes to handle their $atts. - if ( ! empty( $linkmod_classes ) ) { - foreach ( $linkmod_classes as $link_class ) { - if ( ! empty( $link_class ) ) { - - // Check for special class types and set a flag for them. - if ( 'dropdown-header' === $link_class ) { - $linkmod_type = 'dropdown-header'; - } elseif ( 'dropdown-divider' === $link_class ) { - $linkmod_type = 'dropdown-divider'; - } elseif ( 'dropdown-item-text' === $link_class ) { - $linkmod_type = 'dropdown-item-text'; - } + return $classes; + } + + /** + * Returns a string containing a linkmod type and updates the $atts + * array accordingly depending on the decided. + * + * @since 4.0.0 + * + * @param array $linkmod_classes Array of any link modifier classes. + * @return string Empty for default, a linkmod type string otherwise. + */ + private function get_linkmod_type( $linkmod_classes = array() ) { + $linkmod_type = ''; + // Loop through array of linkmod classes to handle their $atts. + if ( ! empty( $linkmod_classes ) ) { + foreach ( $linkmod_classes as $link_class ) { + if ( ! empty( $link_class ) ) { + + // Check for special class types and set a flag for them. + if ( 'dropdown-header' === $link_class ) { + $linkmod_type = 'dropdown-header'; + } elseif ( 'dropdown-divider' === $link_class ) { + $linkmod_type = 'dropdown-divider'; + } elseif ( 'dropdown-item-text' === $link_class ) { + $linkmod_type = 'dropdown-item-text'; } } } - return $linkmod_type; } + return $linkmod_type; + } - /** - * Updates the attributes of a nav item depending on the limkmod classes. - * - * @since 4.0.0 - * - * @param array $atts Array of atts for the current link in nav item. - * @param array $linkmod_classes An array of classes that modify link or nav item behaviors or displays. - * @return array Maybe updated array of attributes for item. - */ - private function update_atts_for_linkmod_type( $atts = array(), $linkmod_classes = array() ) { - if ( ! empty( $linkmod_classes ) ) { - foreach ( $linkmod_classes as $link_class ) { - if ( ! empty( $link_class ) ) { - /* - * Update $atts with a space and the extra classname - * so long as it's not a sr-only class. - */ - if ( 'sr-only' !== $link_class ) { - $atts['class'] .= ' ' . esc_attr( $link_class ); - } - // Check for special class types we need additional handling for. - if ( 'disabled' === $link_class ) { - // Convert link to '#' and unset open targets. - $atts['href'] = '#'; - unset( $atts['target'] ); - } elseif ( 'dropdown-header' === $link_class || 'dropdown-divider' === $link_class || 'dropdown-item-text' === $link_class ) { - // Store a type flag and unset href and target. - unset( $atts['href'] ); - unset( $atts['target'] ); - } + /** + * Updates the attributes of a nav item depending on the limkmod classes. + * + * @since 4.0.0 + * + * @param array $atts Array of atts for the current link in nav item. + * @param array $linkmod_classes An array of classes that modify link or nav item behaviors or displays. + * @return array Maybe updated array of attributes for item. + */ + private function update_atts_for_linkmod_type( $atts = array(), $linkmod_classes = array() ) { + if ( ! empty( $linkmod_classes ) ) { + foreach ( $linkmod_classes as $link_class ) { + if ( ! empty( $link_class ) ) { + /* + * Update $atts with a space and the extra classname + * so long as it's not a sr-only class. + */ + if ( 'sr-only' !== $link_class ) { + $atts['class'] .= ' ' . esc_attr( $link_class ); + } + // Check for special class types we need additional handling for. + if ( 'disabled' === $link_class ) { + // Convert link to '#' and unset open targets. + $atts['href'] = '#'; + unset( $atts['target'] ); + } elseif ( 'dropdown-header' === $link_class || 'dropdown-divider' === $link_class || 'dropdown-item-text' === $link_class ) { + // Store a type flag and unset href and target. + unset( $atts['href'] ); + unset( $atts['target'] ); } } } - return $atts; } + return $atts; + } - /** - * Wraps the passed text in a screen reader only class. - * - * @since 4.0.0 - * - * @param string $text The string of text to be wrapped in a screen reader class. - * @return string The string wrapped in a span with the class. - */ - private function wrap_for_screen_reader( $text = '' ) { - if ( $text ) { - $text = '' . $text . ''; - } - return $text; + /** + * Wraps the passed text in a screen reader only class. + * + * @since 4.0.0 + * + * @param string $text The string of text to be wrapped in a screen reader class. + * @return string The string wrapped in a span with the class. + */ + private function wrap_for_screen_reader( $text = '' ) { + if ( $text ) { + $text = '' . $text . ''; } + return $text; + } - /** - * Returns the correct opening element and attributes for a linkmod. - * - * @since 4.0.0 - * - * @param string $linkmod_type A string containing a linkmod type flag. - * @param string $attributes A string of attributes to add to the element. - * @return string A string with the opening tag for the element with attribibutes added. - */ - private function linkmod_element_open( $linkmod_type, $attributes = '' ) { - $output = ''; - if ( 'dropdown-item-text' === $linkmod_type ) { - $output .= ''; - } elseif ( 'dropdown-header' === $linkmod_type ) { - /* - * For a header use a span with the .h6 class instead of a real - * header tag so that it doesn't confuse screen readers. - */ - $output .= ''; - } elseif ( 'dropdown-divider' === $linkmod_type ) { - // This is a divider. - $output .= ''; } + return $output; + } - /** - * Flattens a multidimensional array to a simple array. - * - * @param array $array A multidimensional array. - * @return array A simple array. - */ - public function flatten( $array ) { - $result = array(); - foreach ( $array as $element ) { - if ( is_array( $element ) ) { - array_push( $result, ...$this->flatten( $element ) ); - } else { - $result[] = $element; - } + /** + * Flattens a multidimensional array to a simple array. + * + * @param array $array A multidimensional array. + * @return array A simple array. + */ + public function flatten( $array ) { + $result = array(); + foreach ( $array as $element ) { + if ( is_array( $element ) ) { + array_push( $result, ...$this->flatten( $element ) ); + } else { + $result[] = $element; } - return $result; } + return $result; + } - /** - * Retrieves the Bootstrap version to use. - * - * @param WP_Nav_Menu_Args $args An object of `wp_nav_menu()` arguments. - * @return int Major Bootstrap version - */ - private function get_bs_version( $args ) { - if ( property_exists( $args, 'bs_version' ) && 5 === (int) $args->bs_version ) { - return (int) $args->bs_version; - } - return $this->bs_version; + /** + * Retrieves the Bootstrap version to use. + * + * @param WP_Nav_Menu_Args $args An object of `wp_nav_menu()` arguments. + * @return int Major Bootstrap version + */ + private function get_bs_version( $args ) { + if ( property_exists( $args, 'bs_version' ) && 5 === (int) $args->bs_version ) { + return (int) $args->bs_version; } + return $this->bs_version; } - -endif; +} From 5d3fbf0960b8ea6c00ecfb6345a7baae5218a5b1 Mon Sep 17 00:00:00 2001 From: IanDelMar <42134098+IanDelMar@users.noreply.github.com> Date: Fri, 12 Nov 2021 07:12:29 +0100 Subject: [PATCH 10/10] Fix identation --- class-wp-bootstrap-navwalker.php | 92 ++++++++++++++++---------------- 1 file changed, 46 insertions(+), 46 deletions(-) diff --git a/class-wp-bootstrap-navwalker.php b/class-wp-bootstrap-navwalker.php index d659b4b..06604e1 100644 --- a/class-wp-bootstrap-navwalker.php +++ b/class-wp-bootstrap-navwalker.php @@ -90,12 +90,12 @@ public function start_lvl( &$output, $depth = 0, $args = null ) { $class_names = $class_names ? ' class="' . esc_attr( $class_names ) . '"' : ''; /* - * The `.dropdown-menu` container needs to have a labelledby - * attribute which points to it's trigger link. - * - * Form a string for the labelledby attribute from the the latest - * link with an id that was added to the $output. - */ + * The `.dropdown-menu` container needs to have a labelledby + * attribute which points to it's trigger link. + * + * Form a string for the labelledby attribute from the the latest + * link with an id that was added to the $output. + */ $labelledby = ''; // Find all links with an id in the output. preg_match_all( '/(/im', $output, $matches ); @@ -140,28 +140,28 @@ public function start_el( &$output, $item, $depth = 0, $args = null, $id = 0 ) { $classes = empty( $item->classes ) ? array() : (array) $item->classes; /* - * Updating the CSS classes of a menu item in the WordPress - * Customizer preview results in all classes defined in that - * particular input box to come in as one big class string. - */ + * Updating the CSS classes of a menu item in the WordPress + * Customizer preview results in all classes defined in that + * particular input box to come in as one big class string. + */ $split_on_spaces = function ( $class ) { return preg_split( '/\s+/', $class ); }; $classes = $this->flatten( array_map( $split_on_spaces, $classes ) ); /* - * Initialize some holder variables to store specially handled item - * wrappers and icons. - */ + * Initialize some holder variables to store specially handled item + * wrappers and icons. + */ $linkmod_classes = array(); $icon_classes = array(); /* - * Get an updated $classes array without linkmod or icon classes. - * - * NOTE: linkmod and icon class arrays are passed by reference and - * are maybe modified before being used later in this function. - */ + * Get an updated $classes array without linkmod or icon classes. + * + * NOTE: linkmod and icon class arrays are passed by reference and + * are maybe modified before being used later in this function. + */ $classes = $this->separate_linkmods_and_icons_from_classes( $classes, $linkmod_classes, $icon_classes, $depth ); // Join any icon classes plucked from $classes into a string. @@ -186,9 +186,9 @@ public function start_el( &$output, $item, $depth = 0, $args = null, $id = 0 ) { } /* - * Whether the current item is active or the item is an ancestor of - * an active item. - */ + * Whether the current item is active or the item is an ancestor of + * an active item. + */ $is_active = false; if ( $item->current || $item->current_item_ancestor ) { if ( ! ( $item->current_item_ancestor && 1 === $args->depth ) ) { @@ -309,9 +309,9 @@ public function start_el( &$output, $item, $depth = 0, $args = null, $id = 0 ) { $item_output = isset( $args->before ) ? $args->before : ''; /* - * This is the start of the internal nav item. Depending on what - * kind of linkmod we have we may need different wrapper elements. - */ + * This is the start of the internal nav item. Depending on what + * kind of linkmod we have we may need different wrapper elements. + */ if ( '' !== $linkmod_type ) { // Is linkmod, output the required element opener. $item_output .= $this->linkmod_element_open( $linkmod_type, $attributes ); @@ -321,10 +321,10 @@ public function start_el( &$output, $item, $depth = 0, $args = null, $id = 0 ) { } /* - * Initiate empty icon var, then if we have a string containing any - * icon classes form the icon markup with an element. This is - * output inside of the item before the $title (the link text). - */ + * Initiate empty icon var, then if we have a string containing any + * icon classes form the icon markup with an element. This is + * output inside of the item before the $title (the link text). + */ $icon_html = ''; if ( ! empty( $icon_class_string ) ) { // Append an with the icon classes to what is output before links. @@ -359,9 +359,9 @@ public function start_el( &$output, $item, $depth = 0, $args = null, $id = 0 ) { $item_output .= isset( $args->link_before ) ? $args->link_before . $icon_html . $title . $args->link_after : ''; /* - * This is the end of the internal nav item. We need to close the - * correct element depending on the type of link or link mod. - */ + * This is the end of the internal nav item. We need to close the + * correct element depending on the type of link or link mod. + */ if ( '' !== $linkmod_type ) { // Is linkmod, output the required closing element. $item_output .= $this->linkmod_element_close( $linkmod_type ); @@ -475,18 +475,18 @@ private function separate_linkmods_and_icons_from_classes( $classes, &$linkmod_c // Loop through $classes array to find linkmod or icon classes. foreach ( $classes as $key => $class ) { /* - * If any special classes are found, store the class in it's - * holder array and and unset the item from $classes. - */ + * If any special classes are found, store the class in it's + * holder array and and unset the item from $classes. + */ if ( preg_match( '/^disabled|^sr-only/i', $class ) ) { // Test for .disabled or .sr-only classes. $linkmod_classes[] = $class; unset( $classes[ $key ] ); } elseif ( preg_match( '/^dropdown-header|^dropdown-divider|^dropdown-item-text/i', $class ) && $depth > 0 ) { /* - * Test for .dropdown-header or .dropdown-divider and a - * depth greater than 0 - IE inside a dropdown. - */ + * Test for .dropdown-header or .dropdown-divider and a + * depth greater than 0 - IE inside a dropdown. + */ $linkmod_classes[] = $class; unset( $classes[ $key ] ); } elseif ( preg_match( '/^fa-(\S*)?|^fa(s|r|l|b)?(\s?)?$/i', $class ) ) { @@ -547,9 +547,9 @@ private function update_atts_for_linkmod_type( $atts = array(), $linkmod_classes foreach ( $linkmod_classes as $link_class ) { if ( ! empty( $link_class ) ) { /* - * Update $atts with a space and the extra classname - * so long as it's not a sr-only class. - */ + * Update $atts with a space and the extra classname + * so long as it's not a sr-only class. + */ if ( 'sr-only' !== $link_class ) { $atts['class'] .= ' ' . esc_attr( $link_class ); } @@ -599,9 +599,9 @@ private function linkmod_element_open( $linkmod_type, $attributes = '' ) { $output .= ''; } elseif ( 'dropdown-header' === $linkmod_type ) { /* - * For a header use a span with the .h6 class instead of a real - * header tag so that it doesn't confuse screen readers. - */ + * For a header use a span with the .h6 class instead of a real + * header tag so that it doesn't confuse screen readers. + */ $output .= ''; } elseif ( 'dropdown-divider' === $linkmod_type ) { // This is a divider. @@ -622,9 +622,9 @@ private function linkmod_element_close( $linkmod_type ) { $output = ''; if ( 'dropdown-header' === $linkmod_type || 'dropdown-item-text' === $linkmod_type ) { /* - * For a header use a span with the .h6 class instead of a real - * header tag so that it doesn't confuse screen readers. - */ + * For a header use a span with the .h6 class instead of a real + * header tag so that it doesn't confuse screen readers. + */ $output .= ''; } elseif ( 'dropdown-divider' === $linkmod_type ) { // This is a divider.