diff --git a/README.md b/README.md index be9e978..0c10f9e 100644 --- a/README.md +++ b/README.md @@ -72,7 +72,7 @@ wp_nav_menu( array( 'container_id' => 'bs-example-navbar-collapse-1', 'menu_class' => 'navbar-nav mr-auto', 'fallback_cb' => 'WP_Bootstrap_Navwalker::fallback', - 'walker' => new WP_Bootstrap_Navwalker(), + 'walker' => new \WP_Bootstrap\WP_Bootstrap_Navwalker(), ) ); ``` @@ -97,7 +97,7 @@ Typically the menu is wrapped with additional markup, here is an example of a ` 'container_id' => 'bs-example-navbar-collapse-1', 'menu_class' => 'nav navbar-nav', 'fallback_cb' => 'WP_Bootstrap_Navwalker::fallback', - 'walker' => new WP_Bootstrap_Navwalker(), + 'walker' => new \WP_Bootstrap\WP_Bootstrap_Navwalker(), ) ); ?> @@ -120,7 +120,7 @@ There has been some interest in making this walker the default walker for all me ```php function prefix_modify_nav_menu_args( $args ) { return array_merge( $args, array( - 'walker' => WP_Bootstrap_Navwalker(), + 'walker' => \WP_Bootstrap\WP_Bootstrap_Navwalker(), ) ); } add_filter( 'wp_nav_menu_args', 'prefix_modify_nav_menu_args' ); diff --git a/app/WP_Bootstrap_Navwalker.php b/app/WP_Bootstrap_Navwalker.php new file mode 100644 index 0000000..2e93f19 --- /dev/null +++ b/app/WP_Bootstrap_Navwalker.php @@ -0,0 +1,580 @@ +item_spacing) && 'discard' === $args->item_spacing) { + $t = ''; + $n = ''; + } else { + $t = "\t"; + $n = "\n"; + } + $indent = str_repeat($t, $depth); + // Default class to add to the file. + $classes = array( 'dropdown-menu' ); + /** + * Filters the CSS class(es) applied to a menu list element. + * + * @since WP 4.8.0 + * + * @param array $classes The CSS classes that are applied to the menu `'; + if ($container) { + $fallback_output .= ''; + } + + // if $args has 'echo' key and it's true echo, otherwise return. + if (array_key_exists('echo', $args) && $args['echo']) { + echo $fallback_output; // WPCS: XSS OK. + } else { + return $fallback_output; + } + } + } + + + /** + * Find 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 seporate_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) { + // 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; + } + + + /** + * Return a string containing a linkmod type and update $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; + } + + + /** + * Update 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; + } + + + /** + * 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 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. + */ + 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; + } +} diff --git a/class-wp-bootstrap-navwalker.php b/class-wp-bootstrap-navwalker.php deleted file mode 100644 index cd598e1..0000000 --- a/class-wp-bootstrap-navwalker.php +++ /dev/null @@ -1,555 +0,0 @@ -item_spacing ) && 'discard' === $args->item_spacing ) { - $t = ''; - $n = ''; - } else { - $t = "\t"; - $n = "\n"; - } - $indent = str_repeat( $t, $depth ); - // Default class to add to the file. - $classes = array( 'dropdown-menu' ); - /** - * Filters the CSS class(es) applied to a menu list element. - * - * @since WP 4.8.0 - * - * @param array $classes The CSS classes that are applied to the menu `'; - if ( $container ) { - $fallback_output .= ''; - } - - // if $args has 'echo' key and it's true echo, otherwise return. - if ( array_key_exists( 'echo', $args ) && $args['echo'] ) { - echo $fallback_output; // WPCS: XSS OK. - } else { - return $fallback_output; - } - } - } - - /** - * Find 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 seporate_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 ) { - // 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; - } - - /** - * Return a string containing a linkmod type and update $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; - } - - /** - * Update 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; - } - - /** - * 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 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. - */ - 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; - } - } -} diff --git a/composer.json b/composer.json index ede2ee2..3006bb6 100644 --- a/composer.json +++ b/composer.json @@ -1,36 +1,44 @@ { - "name": "wp-bootstrap/wp-bootstrap-navwalker", - "description": "A custom WordPress nav walker class to fully implement the Bootstrap 4 navigation style in a custom theme using the WordPress built in menu manager.", - "type": "library", - "license": "GPL-3.0+", - "authors": [ - { - "name": "Brandon Hubbard" - }, - { - "name": "William Patton", - "email": "will@pattonwebz.com" - } - ], - "support": { - "issues": "https://github.com/wp-bootstrap/wp-bootstrap-navwalker/issues/", - "source": "https://github.com/wp-bootstrap/wp-bootstrap-navwalker/" - }, - "require": { - "composer/installers": "~1.0" - }, - "require-dev": { - "stevegrunwell/wp-enforcer": "^0.5.0" + "name": "wp-bootstrap/wp-bootstrap-navwalker", + "description": "A custom WordPress nav walker class to fully implement the Bootstrap 4 navigation style in a custom theme using the WordPress built in menu manager.", + "type": "library", + "license": "GPL-3.0+", + "authors": [ + { + "name": "Brandon Hubbard" }, - "archive": { - "exclude": ["/.*", "/composer.lock"] - }, - "scripts": { - "post-install-cmd": [ - "wp-enforcer" - ], - "post-update-cmd": [ - "wp-enforcer" - ] + { + "name": "William Patton", + "email": "will@pattonwebz.com" + } + ], + "support": { + "issues": "https://github.com/wp-bootstrap/wp-bootstrap-navwalker/issues/", + "source": "https://github.com/wp-bootstrap/wp-bootstrap-navwalker/" + }, + "require": { + "composer/installers": "~1.0" + }, + "require-dev": { + "stevegrunwell/wp-enforcer": "^0.5.0" + }, + "archive": { + "exclude": [ + "/.*", + "/composer.lock" + ] + }, + "scripts": { + "post-install-cmd": [ + "wp-enforcer" + ], + "post-update-cmd": [ + "wp-enforcer" + ] + }, + "autoload": { + "psr-4": { + "WP_Bootstrap\\": "app/" } + } } diff --git a/composer.lock b/composer.lock index 0c8c6ff..2722d93 100644 --- a/composer.lock +++ b/composer.lock @@ -4,8 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file", "This file is @generated automatically" ], - "hash": "5c2a5bddc76de7a32adb1d4fdef8a55b", - "content-hash": "9bf4aac6b0662987ce039e3b148795e4", + "content-hash": "41129a88181f35722e90d09c07bf881c", "packages": [ { "name": "composer/installers", @@ -125,22 +124,22 @@ "zend", "zikula" ], - "time": "2017-12-29 09:13:20" + "time": "2017-12-29T09:13:20+00:00" } ], "packages-dev": [ { "name": "squizlabs/php_codesniffer", - "version": "3.2.3", + "version": "3.3.1", "source": { "type": "git", "url": "https://github.com/squizlabs/PHP_CodeSniffer.git", - "reference": "4842476c434e375f9d3182ff7b89059583aa8b27" + "reference": "628a481780561150481a9ec74709092b9759b3ec" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/4842476c434e375f9d3182ff7b89059583aa8b27", - "reference": "4842476c434e375f9d3182ff7b89059583aa8b27", + "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/628a481780561150481a9ec74709092b9759b3ec", + "reference": "628a481780561150481a9ec74709092b9759b3ec", "shasum": "" }, "require": { @@ -178,7 +177,7 @@ "phpcs", "standards" ], - "time": "2018-02-20 21:35:23" + "time": "2018-07-26T23:47:18+00:00" }, { "name": "stevegrunwell/wp-enforcer", @@ -219,28 +218,31 @@ "git hooks", "wordpress" ], - "time": "2017-05-28 18:44:13" + "time": "2017-05-28T18:44:13+00:00" }, { "name": "wp-coding-standards/wpcs", - "version": "0.14.1", + "version": "1.0.0", "source": { "type": "git", "url": "https://github.com/WordPress-Coding-Standards/WordPress-Coding-Standards.git", - "reference": "cf6b310caad735816caef7573295f8a534374706" + "reference": "539c6d74e6207daa22b7ea754d6f103e9abb2755" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/WordPress-Coding-Standards/WordPress-Coding-Standards/zipball/cf6b310caad735816caef7573295f8a534374706", - "reference": "cf6b310caad735816caef7573295f8a534374706", + "url": "https://api.github.com/repos/WordPress-Coding-Standards/WordPress-Coding-Standards/zipball/539c6d74e6207daa22b7ea754d6f103e9abb2755", + "reference": "539c6d74e6207daa22b7ea754d6f103e9abb2755", "shasum": "" }, "require": { "php": ">=5.3", "squizlabs/php_codesniffer": "^2.9.0 || ^3.0.2" }, + "require-dev": { + "phpcompatibility/php-compatibility": "*" + }, "suggest": { - "dealerdirect/phpcodesniffer-composer-installer": "^0.4.3" + "dealerdirect/phpcodesniffer-composer-installer": "^0.4.3 || This Composer plugin will sort out the PHPCS 'installed_paths' automatically." }, "type": "phpcodesniffer-standard", "notification-url": "https://packagist.org/downloads/", @@ -259,7 +261,7 @@ "standards", "wordpress" ], - "time": "2018-02-16 01:57:48" + "time": "2018-07-25T18:10:35+00:00" } ], "aliases": [],