Я мав ще трохи часу, щоб розібратися в цьому сам (вибачте, якщо я втратив чийсь час), і я зрозумів, що для мене найкращим способом вирішити проблему виділення буде щось, щоб щось робити _wp_menu_item_classes_by_context()
, що робиться, тобто ітерація над усіма батьки та предки пункту меню, який виступає батьком мого спеціального типу публікації, і додають класи відповідно.
Оскільки я також хотів, щоб батьківська сторінка для мого користувальницького типу публікації була виправлена та легко змінювалася, не потребуючи оновлення всіх публікацій, як тільки батько зміниться, я вирішив використовувати варіант замість заповнення post_parent
поле моїх власних публікацій типу публікацій. Я використовував ACF для цього, оскільки я все-таки використовую його у своїй темі, але, звичайно, функція WordPress за замовчуванням, звичайно, зробить це теж.
Для моїх потреб я міг би скористатися wp_nav_menu_objects
фільтром. Крім того, мені довелося фільтрувати page_for_posts
параметр, щоб він повертав помилково / порожнє значення, це дозволяє уникнути також виділення сторінки публікацій за замовчуванням.
Зауважте, що я не пройшов весь шлях, фільтр додає лише класи current-menu-ancestor
та current-menu-parent
класи, оскільки цього було достатньо для моїх потреб!
/**
* Filters the `page_for_posts` option on specific custom post types in
* order to avoid the wrong menu item being marked as
* `current-page-parent`.
*
* @see _wp_menu_item_classes_by_context()
*/
function wpse13308_pre_option_page_for_posts_filter()
{
$types = array
(
'my_custom_post_type_x',
'my_custom_post_type_y',
'my_custom_post_type_z'
);
if(in_array(get_post_type(), $types))
{
return 0;
}
return false;
}
add_filter('pre_option_page_for_posts', 'wpse13308_pre_option_page_for_posts_filter');
/**
* Returns the current posts parent page ID
*
* @return int
*/
function wpse13308_get_parent_page_id()
{
$postType = get_post_type();
$parentPageId = null;
switch($postType)
{
case 'my_custom_post_type_x':
case 'my_custom_post_type_y':
case 'my_custom_post_type_z':
$parentPageId = (int)get_field('page_for_' . $postType, 'options')->ID;
break;
case 'post':
$parentPageId = (int)get_option('page_for_posts');
break;
}
return $parentPageId;
}
/**
* Adds proper context based classes so that the parent menu items are
* being highlighted properly for custom post types and regular posts.
*
* @param array $menuItems
* @return array
*
* @see _wp_menu_item_classes_by_context()
*/
function wpse13308_wp_nav_menu_objects_filter(array $menuItems)
{
$parentPageId = wpse13308_get_parent_page_id();
if($parentPageId !== null)
{
$activeAncestorItemIds = array();
$activeParentItemIds = array();
foreach($menuItems as $menuItem)
{
if((int)$parentPageId === (int)$menuItem->object_id)
{
$ancestorId = (int)$menuItem->db_id;
while
(
($ancestorId = (int)get_post_meta($ancestorId, '_menu_item_menu_item_parent', true)) &&
!in_array($ancestorId, $activeAncestorItemIds)
)
{
$activeAncestorItemIds[] = $ancestorId;
}
$activeParentItemIds[] = (int)$menuItem->db_id;
}
}
$activeAncestorItemIds = array_filter(array_unique($activeAncestorItemIds));
$activeParentItemIds = array_filter(array_unique($activeParentItemIds));
foreach($menuItems as $key => $menuItem)
{
$classes = $menuItems[$key]->classes;
if(in_array(intval($menuItem->db_id), $activeAncestorItemIds))
{
$classes[] = 'current-menu-ancestor';
$menuItems[$key]->current_item_ancestor = true;
}
if(in_array($menuItem->db_id, $activeParentItemIds))
{
$classes[] = 'current-menu-parent';
$menuItems[$key]->current_item_parent = true;
}
$menuItems[$key]->classes = array_unique($classes);
}
}
return $menuItems;
}
add_filter('wp_nav_menu_objects', 'wpse13308_wp_nav_menu_objects_filter');
Заради повноти, коли замість використання параметрів post_parent
(див. Відповідь @ Bainternet ) замість параметрів, отримання батьківського ідентифікатора може виглядати приблизно так:
/**
* Returns the current posts parent page ID
*
* @return int
*/
function wpse13308_get_parent_page_id()
{
$parentPageId = null;
$post = get_post();
switch($post->post_type)
{
case 'my_custom_post_type_x':
case 'my_custom_post_type_y':
case 'my_custom_post_type_z':
$parentPageId = (int)$post->post_parent;
break;
case 'post':
$parentPageId = (int)get_option('page_for_posts');
break;
}
return $parentPageId;
}