我已经解决了这个问题,并且认为我已经找到了解决方案。请随时对以下内容进行修改或改进!
此功能可以看作是一系列5个步骤:
收集有关移动的信息(子级、其旧父级和其新父级)
查找相应的菜单项(子级、其旧父级和其新父级)将子级移动到相应的新父级;1。收集有关移动的信息首先,我们需要在移动之前和之后获取页面的副本。我用了两个钩子:pre_post_update
和save_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;
}