使菜单结构与页面父级更改时的页面层次结构匹配

时间:2015-11-20 作者:James Cushing

像twentyten这样的旧WordPress主题包含的功能允许nav菜单结构反映页面继承权的变化。例如,如果我具有以下任意页面继承结构(和匹配的菜单结构):

如果我要编辑页面“II”并将其父级从“B”更改为“C”,则我的主导航菜单的结构将立即更新以反映该更改。

但是,对于后来的主题,如Twenty15(以及第三方模板),此功能不存在。我已经查看了函数。除非我忽略了一些东西,否则无法找到从那里调用该功能的证据。

所以很自然,我想开始创建自己的函数。我该怎么做?

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

我已经解决了这个问题,并且认为我已经找到了解决方案。请随时对以下内容进行修改或改进!

此功能可以看作是一系列5个步骤:

收集有关移动的信息(子级、其旧父级和其新父级)

  • 查找相应的菜单项(子级、其旧父级和其新父级)
  • 将子级移动到相应的新父级;

    1。收集有关移动的信息首先,我们需要在移动之前和之后获取页面的副本。我用了两个钩子:pre_post_updatesave_post_page. 如果父级已更改(因为这些挂钩将在每次页面更新时运行),它将调用一个名为menu_match 我将在后续步骤中记录。

    // Re-initialise post vars to prevent accidental moves
    $old_post = NULL;
    $new_post = NULL;
    
    // Capture the post details before they change
    add_action(\'pre_post_update\', \'get_old_post_version\');
    function get_old_post_version($postID){
        global $old_post;
        $old_post = get_post($postID);
    }
    
    // Get the updated post details
    add_action(\'save_post_page\', \'get_new_post_version\');
    function get_new_post_version($postID){
        global $old_post, $new_post;
        $new_post = get_post($postID);
    
        // If the parent has changed, make the menu match the new heirarchy
        if($old_post->post_parent != $new_post->post_parent){
            menu_match($old_post, $new_post);
        }
    }
    
    nbsp;

    2。找到合适的菜单项,此步骤和步骤3的代码都将在步骤3的下面,因为它们是相同功能的一部分,我认为将它们放在一起阅读会更好。

    此步骤包括获取给定菜单的项目(该菜单的ID将为要附加到页面继承权限的菜单指定),然后将它们推到一个数组(用于子菜单),如果object_id (它们所代表的项的ID)匹配旧页的ID,或者匹配另一个数组(对于父项),如果object_id 匹配旧页的post_parent (作为旧页父级的页的ID)。

    注:我说的是“旧页面”,意思是页面的旧版本。此处没有“删除并重新创建”。

    如果发现多个子项和/或父项,我们将通过检查子项是否menu_item_parent (其父菜单项的ID)与父菜单项的ID匹配。。。很简单,对吧?

    最后,我们找到新的父项(其object_id 匹配new 第页的post_parent).

     ;

    3。将子级移动到适当的新父级,这一步只需调用wp_update_nav_menu_item 为了用新的父ID更新子项,我还恢复了一些其他属性以保持健全。

     ;

    这个menu_match 功能如下-这是我第一次提交“回答你自己的问题”,所以如果我用了完全错误的方法,请告诉我!还有一些“待办事项”评论,建议对功能进行改进。。。我相信会有一个更干净的方法来做这件事,但这是我用过的方法!

    function menu_match(&$old_post, &$new_post){
        // Set menu which we\'re manipulating...
        $menuID = 2;
        // ... and get its items
        $menu_items = wp_get_nav_menu_items($menuID);
    
        // Find all items which link to the page in question
        $old_child_items = array();
        foreach($menu_items as $m_item){
            if($m_item->object_id == $old_post->ID){
                array_push($old_child_items, $m_item);  
            }
        }
    
        // If the post isn\'t top level, find all items which link to the parent in question
        $old_parent_items = array();
        if($old_post->post_parent != 0){
            foreach($menu_items as $m_item){
                if($m_item->object_id == $old_post->post_parent){
                    array_push($old_parent_items, $m_item);
                }
            }
        }
    
        // Pick the correct child (and parent if necessary)
        $child = NULL;
        $old_parent = NULL;
        foreach($old_child_items as $child_candidate){
            if(count($old_parent_items) > 0){
                // If there are parent items to look through, find the one which has the right ID
                foreach($old_parent_items as $parent_candidate){
                    if($child_candidate->menu_item_parent == $parent_candidate->ID){
                        $child = $child_candidate;
                        $old_parent = $parent_candidate;
                    }
                }
            }else{
                // If there are no parent items, pick the child item which has no parent
                if($child_candidate->menu_item_parent == 0){
                    $child = $child_candidate;
                }
            }
        }
    
        if($child != NULL){
            // If the post isn\'t moving to top level, find all items which link to the new parent
            if($new_post->post_parent != 0){
                $new_parent_items = array();
                foreach($menu_items as $m_item){
                    if($m_item->object_id == $new_post->post_parent){
                        array_push($new_parent_items, $m_item);
                    }
                }
    
                // TODO:    Add recursive upwards search in the event that there are two menu items
                //          for the desired parent.
                //
                // For now, assume the first match is correct, as there shouldn\'t be more than one
                // item pointing to the same parent.
                if(count($new_parent_items) > 0){
                    $new_parentID = $new_parent_items[0]->ID;
                }else{
                    // If no matches are found, put the item on the top level
                    $new_parentID = 0;  
                }
            }else{
                // Post is moving to top level
                $new_parent_items = NULL;
                $new_parentID = 0;  
            }
    
            // Update the menu item with the new parent (and reinstate existing properties for sanity)
            $menu_update = wp_update_nav_menu_item($menuID, $child->db_id, array(
                \'menu-item-status\' => $child->post_status,
                \'menu-item-post-name\' => $child->post_name,
                \'menu-item-type\' => $child->post_type,
                \'menu-item-parent-id\' => $new_parentID,
                \'menu-item-object-id\' => $child->object_id,
                \'menu-item-object\' => $child->object,
                \'menu-item-type\' => $child->type,
                \'menu-item-type-label\' => $child->type_label,
                \'menu-item-url\' => $child->url
            ));
        }
    
        // TODO:    Handle overrides (in case a page doesn\'t want putting in the menu or
        //          moving from its current location)
    
        return;
    }
    

  • 相关推荐

    具有Get_Pages的多个元密钥

    我目前有以下代码,其中我按页面模板过滤;$pages = get_pages( array( ‘post_type’ => ‘page’, ‘meta_key’ => ‘_wp_page_template’, ‘meta_value’ => ‘unit.php’, ‘hierarchical’ => 0 ) ); 我还想按ACF字段排序,因此需要添加以下内容:;‘meta_key’ => ‘status’, ‘ord