函数文档

wp_map_nav_menu_locations()

💡 云策文档标注

概述

wp_map_nav_menu_locations() 函数用于在主题切换时,根据之前活动主题的导航菜单位置分配,将旧菜单映射到新主题的注册位置。它通过参数处理、简单映射和智能猜测来确保菜单配置的连续性。

关键要点

  • 函数接受两个数组参数:$new_nav_menu_locations(新主题的菜单位置分配)和 $old_nav_menu_locations(旧主题的菜单位置分配),返回映射后的新位置数组。
  • 映射过程包括:过滤新位置为已注册位置、处理空旧位置、单位置直接映射、相同slug位置映射,以及基于常见slug组进行智能匹配。
  • 使用 get_registered_nav_menus() 获取注册位置,并定义 $common_slug_groups 来辅助猜测映射,如将 'primary'、'menu-1' 等视为同一组。
  • 函数在 WordPress 4.9.0 中引入,主要用于 _wp_menus_changed() 和 WP_Customize_Nav_Menus::customize_register() 等场景,处理主题变更后的菜单配置。

代码示例

function wp_map_nav_menu_locations( $new_nav_menu_locations, $old_nav_menu_locations ) {
    $registered_nav_menus   = get_registered_nav_menus();
    $new_nav_menu_locations = array_intersect_key( $new_nav_menu_locations, $registered_nav_menus );

    // Short-circuit if there are no old nav menu location assignments to map.
    if ( empty( $old_nav_menu_locations ) ) {
        return $new_nav_menu_locations;
    }

    // If old and new theme have just one location, map it and we're done.
    if ( 1 === count( $old_nav_menu_locations ) && 1 === count( $registered_nav_menus ) ) {
        $new_nav_menu_locations[ key( $registered_nav_menus ) ] = array_pop( $old_nav_menu_locations );
        return $new_nav_menu_locations;
    }

    $old_locations = array_keys( $old_nav_menu_locations );

    // Map locations with the same slug.
    foreach ( $registered_nav_menus as $location => $name ) {
        if ( in_array( $location, $old_locations, true ) ) {
            $new_nav_menu_locations[ $location ] = $old_nav_menu_locations[ $location ];
            unset( $old_nav_menu_locations[ $location ] );
        }
    }

    // If there are no old nav menu locations left, then we're done.
    if ( empty( $old_nav_menu_locations ) ) {
        return $new_nav_menu_locations;
    }

    /*
     * If old and new theme both have locations that contain phrases
     * from within the same group, make an educated guess and map it.
     */
    $common_slug_groups = array(
        array( 'primary', 'menu-1', 'main', 'header', 'navigation', 'top' ),
        array( 'secondary', 'menu-2', 'footer', 'subsidiary', 'bottom' ),
        array( 'social' ),
    );

    // Go through each group...
    foreach ( $common_slug_groups as $slug_group ) {

        // ...and see if any of these slugs...
        foreach ( $slug_group as $slug ) {

            // ...and any of the new menu locations...
            foreach ( $registered_nav_menus as $new_location => $name ) {

                // ...actually match!
                if ( is_string( $new_location ) && false === stripos( $new_location, $slug ) && false === stripos( $slug, $new_location ) ) {
                    continue;
                } elseif ( is_numeric( $new_location ) && $new_location !== $slug ) {
                    continue;
                }

                // Then see if any of the old locations...
                foreach ( $old_nav_menu_locations as $location => $menu_id ) {

                    // ...and any slug in the same group...
                    foreach ( $slug_group as $slug ) {

                        // ... have a match as well.
                        if ( is_string( $location ) && false === stripos( $location, $slug ) && false === stripos( $slug, $location ) ) {
                            continue;
                        } elseif ( is_numeric( $location ) && $location !== $slug ) {
                            continue;
                        }

                        // Make sure this location wasn't mapped and removed previously.
                        if ( ! empty( $old_nav_menu_locations[ $location ] ) ) {

                            // We have a match that can be mapped!
                            $new_nav_menu_locations[ $new_location ] = $old_nav_menu_locations[ $location ];

                            // Remove the mapped location so it can't be mapped again.
                            unset( $old_nav_menu_locations[ $location ] );

                            // Go back and check the next new menu location.
                            continue 3;
                        }
                    } // End foreach ( $slug_group as $slug ).
                } // End foreach ( $old_nav_menu_locations as $location => $menu_id ).
            } // End foreach foreach ( $registered_nav_menus as $new_location => $name ).
        } // End foreach ( $slug_group as $slug ).
    } // End foreach ( $common_slug_groups as $slug_group ).

    return $new_nav_menu_locations;
}

📄 原文内容

Maps nav menu locations according to assignments in previously active theme.

Parameters

$new_nav_menu_locationsarrayrequired
New nav menu locations assignments.
$old_nav_menu_locationsarrayrequired
Old nav menu locations assignments.

Return

array Nav menus mapped to new nav menu locations.

Source

function wp_map_nav_menu_locations( $new_nav_menu_locations, $old_nav_menu_locations ) {
	$registered_nav_menus   = get_registered_nav_menus();
	$new_nav_menu_locations = array_intersect_key( $new_nav_menu_locations, $registered_nav_menus );

	// Short-circuit if there are no old nav menu location assignments to map.
	if ( empty( $old_nav_menu_locations ) ) {
		return $new_nav_menu_locations;
	}

	// If old and new theme have just one location, map it and we're done.
	if ( 1 === count( $old_nav_menu_locations ) && 1 === count( $registered_nav_menus ) ) {
		$new_nav_menu_locations[ key( $registered_nav_menus ) ] = array_pop( $old_nav_menu_locations );
		return $new_nav_menu_locations;
	}

	$old_locations = array_keys( $old_nav_menu_locations );

	// Map locations with the same slug.
	foreach ( $registered_nav_menus as $location => $name ) {
		if ( in_array( $location, $old_locations, true ) ) {
			$new_nav_menu_locations[ $location ] = $old_nav_menu_locations[ $location ];
			unset( $old_nav_menu_locations[ $location ] );
		}
	}

	// If there are no old nav menu locations left, then we're done.
	if ( empty( $old_nav_menu_locations ) ) {
		return $new_nav_menu_locations;
	}

	/*
	 * If old and new theme both have locations that contain phrases
	 * from within the same group, make an educated guess and map it.
	 */
	$common_slug_groups = array(
		array( 'primary', 'menu-1', 'main', 'header', 'navigation', 'top' ),
		array( 'secondary', 'menu-2', 'footer', 'subsidiary', 'bottom' ),
		array( 'social' ),
	);

	// Go through each group...
	foreach ( $common_slug_groups as $slug_group ) {

		// ...and see if any of these slugs...
		foreach ( $slug_group as $slug ) {

			// ...and any of the new menu locations...
			foreach ( $registered_nav_menus as $new_location => $name ) {

				// ...actually match!
				if ( is_string( $new_location ) && false === stripos( $new_location, $slug ) && false === stripos( $slug, $new_location ) ) {
					continue;
				} elseif ( is_numeric( $new_location ) && $new_location !== $slug ) {
					continue;
				}

				// Then see if any of the old locations...
				foreach ( $old_nav_menu_locations as $location => $menu_id ) {

					// ...and any slug in the same group...
					foreach ( $slug_group as $slug ) {

						// ... have a match as well.
						if ( is_string( $location ) && false === stripos( $location, $slug ) && false === stripos( $slug, $location ) ) {
							continue;
						} elseif ( is_numeric( $location ) && $location !== $slug ) {
							continue;
						}

						// Make sure this location wasn't mapped and removed previously.
						if ( ! empty( $old_nav_menu_locations[ $location ] ) ) {

							// We have a match that can be mapped!
							$new_nav_menu_locations[ $new_location ] = $old_nav_menu_locations[ $location ];

							// Remove the mapped location so it can't be mapped again.
							unset( $old_nav_menu_locations[ $location ] );

							// Go back and check the next new menu location.
							continue 3;
						}
					} // End foreach ( $slug_group as $slug ).
				} // End foreach ( $old_nav_menu_locations as $location => $menu_id ).
			} // End foreach foreach ( $registered_nav_menus as $new_location => $name ).
		} // End foreach ( $slug_group as $slug ).
	} // End foreach ( $common_slug_groups as $slug_group ).

	return $new_nav_menu_locations;
}

Changelog

Version Description
4.9.0 Introduced.