One would expect that a preferred menu link item would be that link item in a menu which is the default or primary menu link item for any particular path where more than one menu link exists in the same menu with the same link path. For example, when you create a new node instance which allows for menu link creation within the node edit form, it would be expected that when the node is fully loaded (therefore contains the property menu
as an array which is loaded via the invocation of hook_node_prepare
that is implemented by the menu module) the $node->menu
represents the preferred menu link for this node. While we can significantly rely on this method for any node's menu link when retrieved via a node object ($node->menu
), we cannot expect to be the same as what may be returned from menu_link_get_preferred('node/' . $node->nid)
. So which is the the correct preferred menu link?
With the expectation that $node->menu
represents the preferred menu link for the particular $node
, the implementation of the function menu_link_get_preferred()
is incorrect in which it does not retrieve a the first created menu link. The first created menu link is determined with the lowest primary key value ({menu_links}.mlid
). In menu_node_prepare($node)
the query performed to against the {menu_links}
table performs an SQL LIMIT
via Drupal's db_range_query()
and limits the results to one while sorting the rows by the primary key in ascending order. Furthermore, the menu_link_get_preferred()
's implementation bases its "preferred" link determination on the first menu link found, ordered by the order of the menu names returned menu_get_active_menu_names()
which is extremely problematic. For example, if you have a node whose node centric preferred menu link exists in the menu named main-menu
but a menu link item exists in the menu named footer-menu
, if the menu named footer-menu
exists before main-menu
in the returned menu names from menu_get_active_menu_names()
, the menu link which exists in footer-menu
would be noted as the preferred menu link as it was the first found.
TODO: Add additional information and clarification. Propose a solution for the menu_link_get_preferred()
.