当步行者运行时运行过滤器

时间:2014-06-23 作者:JacobTheDev

有没有办法运行特定的add_filter 每当特定Walker_Nav_Menu 课程运行?该函数总是需要在walker运行时运行,我希望它们共享变量,尤其是$column_limit. 该函数应该在walker中所有其他内容之前运行,以便在生成类之前向li添加类。

这整套PHP的目的是在WordPress中启用mega菜单功能。本质上,如果我有这样的标记:

<ul>
    <li><a href="#">Example</a></li>
    <li class="widget">
        <a href="#">Example</a>
        <ul>
            <li><a href="#">Example</a></li>
            <li><a href="#">Example</a></li>
            <li><a href="#">Example</a></li>
            <li class="break"><a href="#">Example</a></li>
            <li><a href="#">Example</a></li>
            <li><a href="#">Example</a></li>
        </ul>
    </li>
    <li><a href="#">Example</a></li>
    <li><a href="#">Example</a></li>
    <li><a href="#">Example</a></li>
</ul>
使用breakwidget 作为用户在WordPress菜单编辑器中添加的类,walker和函数会输出以下内容:

<ul>
    <li><a href="#">Example</a></li>
    <li class="widget mega-menu-columns-3">
        <a href="#">Example</a>
        <section>
            <ul>
                <li><a href="#">Example</a></li>
                <li><a href="#">Example</a></li>
                <li><a href="#">Example</a></li>
            </ul>
            <ul class="sub-menu">
                <li class="break"><a href="#">Example</a></li>
                <li><a href="#">Example</a></li>
                <li><a href="#">Example</a></li>
            </ul>
            <aside>
                <h1>Widget Title</h1>
                <p>Widget text</p>
            </aside>
        </section>
    </li>
    <li><a href="#">Example</a></li>
    <li><a href="#">Example</a></li>
    <li><a href="#">Example</a></li>
</ul>
函数正在添加mega-menu-columns-#<li> 在上述代码中。所有其他的变化都是由步行者进行的。所有这些都可以,但我希望它能以较少的配置工作;本质上,我希望能够设置一次列限制,而不必设置theme_location 在函数中。如果我设置了一个使用walker的菜单,我希望所有PHP都能自动运行。如果这还不够清楚,请进一步澄清。

这是我当前的代码:

// mega menu walker
class megaMenuWalker extends Walker_Nav_Menu {
    private $column_limit = 3; // used to how many columns can be generated (</ul><ul class="sub-menu"> and the widgets)
    private $show_widget = false; // used to determine weather or not to show a widget in the drop down
    private $column_count = 0; // for counting how many columns are in a drop down
    static $li_count = 0; // for counting how many lis are in a drop down, used only to check if the li is first in its list
    function start_el(&$output, $item, $depth = 0, $args = array(), $id = 0) {
        $classes = empty($item->classes) ? array() : (array) $item->classes; // retrive array of classes for each li
        $item_id = $item->ID; // retrieve item id for each li, not really used, keeping it to maintain standard WP menu structure
        if ($depth == 0) {
            self::$li_count = 0; // reset the li counter when we return to the top level in the menu
        }
        if ($depth == 0 && in_array("widget", $classes)) {
            $this->show_widget = true; // show the widget if the top level li has a class of "widget"
            $this->column_count++; // if the widget is shown, increase the column counter by one
        }
        if ($depth == 1 && self::$li_count == 1) {
            $this->column_count++; // if there\'s anything in a drop down, increase the column counter by one
        }
        if ($depth == 1 && in_array("break", $classes) && self::$li_count != 1 && $this->column_count < $this->column_limit) {
            // if we\'re in ul ul, and an li has a class of break, and it\'s not the first in its list, and we haven\'t met the column limit...
            $output .= "</ul><ul class=\\"sub-menu\\">"; // add a break in the list
            $this->column_count++; // increase the column count by one
        }
        $class_names = join(" ", apply_filters("nav_menu_css_class", array_filter($classes), $item)); // set up the classes array to be added as classes to each li
        $class_names = " class=\\"" . esc_attr($class_names) . "\\""; // set up class HTML
        $output .= sprintf(
            "<li id=\\"menu-item-%s\\"%s><a href=\\"%s\\">%s</a>", // output li structure
            $item_id, // not really used, keeping it for standard WP menu structure
            $class_names, // add the class names
            $item->url, // add the URL
            $item->title // add the title
        );
        self::$li_count++; // increase the li counter. Not used except if == 1
    }
    function start_lvl(&$output, $depth = 0, $args = array()) {
        if ($depth == 0) {
            $output .= "<section>"; // if a drop down exists, wrap it in <section>. I\'m not sure why $depth == 0 and not 1, but it works, so I\'m not complaining.
        }
        $output .= "<ul class=\\"sub-menu\\">"; // output standard WP menu UL for drop downs
    }
    function end_lvl(&$output, $depth = 0, $args = array()) {
        $output .= "</ul>"; // close UL for drop downs
        if ($depth == 0) {
            if ($this->show_widget) {
                // if the parent li has a class of widget...
                ob_start();
                dynamic_sidebar("Navigation Callout"); // show the widget
                $widget = ob_get_contents(); // retrieve the widget\'s HTML as a variable
                ob_end_clean(); // clear the shown widget
                $output .= $widget; // show the widget
                $this->show_widget = false; // reset the widget variable to false so the next li doesn\'t get one unless indicated.
                // I know this section is complicated, but it was the only way to correctly display the widget
            }
            $output .= "</section>"; // end the <section> that contains the drop downs.
        }
    }
    function end_el(&$output, $item, $depth = 0, $args = array(), $id = 0) {
        if ($depth == 0 && $this->column_count > 0) {
            $this->column_count = 0; // reset the column counter when a drop down ends.
        }
        $output .= "</li>"; // close the li of each menu item
    }
}

// add mega-menu-columns-# classes
// I didn\'t write this, but I\'ll do my best to explain it
add_filter("wp_nav_menu_objects", function($items, $args) {
    if ("first" !== $args->theme_location) {
        return $items; // don\'t run the function if it\'s not a specific menu. This should really be a check if the walker is set to a menu, not the menu\'s location.
    }
    static $post_id = 0; // set up the post id variable
    static $x_key = 0; // not sure what this is
    static $column_count = 1; // set the initial column count to 1
    static $column_limit = 3; // set the column limit to 3. Ideally would pull from the walker.
    static $li_count = 0; // set up the li counter
    $tmp = array(); // not sure waht this is
    foreach($items as $key => $item) {
        if (0 == $item->menu_item_parent) {
            $x_key = $key; // not sure...
            $post_id = $item->ID; // set the post ID to the item\'s ID
            $column_count = 1; // reset the column count
            $li_count = 0; // reset the li count
            if (in_array("widget", $item->classes, 1)) {
                $column_count++; // if widget is in the li class, add 1 to the column count
            }
        }
        if ($post_id == $item->menu_item_parent) {
            $li_count++; // if an item has children, increase the li count by one
            if (in_array("break", $item->classes, 1) && $li_count > 1 && $column_count < $column_limit) {
                $column_count++; // if break is in the item\'s classes, and the li count isn\'t one, and the column count is\'nt equal to the column limit, increase the counter by one
            }
            $tmp[$x_key] = $column_count; // not sure what this is.
        }
    }
    foreach($tmp as $key => $value) {
        $items[$key]->classes[] = sprintf("mega-menu-columns-%d", $value); // adding the new class based on column count to the lis
    }
    unset($tmp); // not sure
    return $items; // ending the filter
}, PHP_INT_MAX, 2); // not sure

1 个回复
最合适的回答,由SO网友:Rarst 整理而成

如果所有这些都是您自己的代码,那么将其作为walker的一部分实现是合理的。

如果您需要在运行第三方walker时添加过滤器,您可能可以:

将其添加到wp_nav_menu_args 挂钩,检查是否walker 设置为:

add_filter( \'wp_nav_menu_args\', function( $args ) {

    if ( $args[\'walker\'] instanceof megaMenuWalker ) {

        add_filter( \'wp_nav_menu_objects\', \'callback_name_here\' );
    }

    return $args;
} );
在处删除它wp_nav_menu 完全生成菜单标记后挂钩:

add_filter( \'wp_nav_menu\', function( $nav_menu ) {

    remove_filter( \'wp_nav_menu_objects\', \'callback_name_here\' );

    return $nav_menu;
} );

结束

相关推荐

WordPress定向到帖子页面(edit.php)而不是保存帖子

我的身材很好(WordPress 3.9.1 运行214主题)。我已经installed WooCommerce 插件并添加了一个产品。该产品是一种有65种变体的可变产品。当我link all variations 保存,没有问题。但是,编辑任何信息,如库存数量或价格等,并点击更新将导致以下问题。一旦我click Update, 我被重定向到编辑。php(帖子页面)和changes were not saved. 没有错误,一切似乎都很正常。一个接一个地删除变体后,我意识到once there\'s le