danielebarchiesi@4: array( danielebarchiesi@4: 'name' => t('Menus'), danielebarchiesi@4: 'default_hook' => 'menu_default_menu_custom', danielebarchiesi@4: 'feature_source' => TRUE, danielebarchiesi@4: 'default_file' => FEATURES_DEFAULTS_INCLUDED, danielebarchiesi@4: ), danielebarchiesi@4: 'menu_links' => array( danielebarchiesi@4: 'name' => t('Menu links'), danielebarchiesi@4: 'default_hook' => 'menu_default_menu_links', danielebarchiesi@4: 'feature_source' => TRUE, danielebarchiesi@4: 'default_file' => FEATURES_DEFAULTS_INCLUDED, danielebarchiesi@4: ), danielebarchiesi@4: // DEPRECATED danielebarchiesi@4: 'menu' => array( danielebarchiesi@4: 'name' => t('Menu items'), danielebarchiesi@4: 'default_hook' => 'menu_default_items', danielebarchiesi@4: 'default_file' => FEATURES_DEFAULTS_INCLUDED, danielebarchiesi@4: 'feature_source' => FALSE, danielebarchiesi@4: ), danielebarchiesi@4: ); danielebarchiesi@4: } danielebarchiesi@4: danielebarchiesi@4: /** danielebarchiesi@4: * Implements hook_features_export(). danielebarchiesi@4: * DEPRECATED: This implementation simply migrates deprecated `menu` items danielebarchiesi@4: * to the `menu_links` type. danielebarchiesi@4: */ danielebarchiesi@4: function menu_features_export($data, &$export, $module_name = '') { danielebarchiesi@4: $pipe = array(); danielebarchiesi@4: foreach ($data as $path) { danielebarchiesi@4: $pipe['menu_links'][] = "features:{$path}"; danielebarchiesi@4: } danielebarchiesi@4: return $pipe; danielebarchiesi@4: } danielebarchiesi@4: danielebarchiesi@4: /** danielebarchiesi@4: * Implements hook_features_export_options(). danielebarchiesi@4: */ danielebarchiesi@4: function menu_custom_features_export_options() { danielebarchiesi@4: $options = array(); danielebarchiesi@4: $result = db_query("SELECT * FROM {menu_custom} ORDER BY title", array(), array('fetch' => PDO::FETCH_ASSOC)); danielebarchiesi@4: foreach ($result as $menu) { danielebarchiesi@4: $options[$menu['menu_name']] = $menu['title']; danielebarchiesi@4: } danielebarchiesi@4: return $options; danielebarchiesi@4: } danielebarchiesi@4: danielebarchiesi@4: /** danielebarchiesi@4: * Implements hook_features_export(). danielebarchiesi@4: */ danielebarchiesi@4: function menu_custom_features_export($data, &$export, $module_name = '') { danielebarchiesi@4: // Default hooks are provided by the feature module so we need to add danielebarchiesi@4: // it as a dependency. danielebarchiesi@4: $export['dependencies']['features'] = 'features'; danielebarchiesi@4: $export['dependencies']['menu'] = 'menu'; danielebarchiesi@4: danielebarchiesi@4: // Collect a menu to module map danielebarchiesi@4: $pipe = array(); danielebarchiesi@4: $map = features_get_default_map('menu_custom', 'menu_name'); danielebarchiesi@4: foreach ($data as $menu_name) { danielebarchiesi@4: // If this menu is provided by a different module, add it as a dependency. danielebarchiesi@4: if (isset($map[$menu_name]) && $map[$menu_name] != $module_name) { danielebarchiesi@4: $export['dependencies'][$map[$menu_name]] = $map[$menu_name]; danielebarchiesi@4: } danielebarchiesi@4: else { danielebarchiesi@4: $export['features']['menu_custom'][$menu_name] = $menu_name; danielebarchiesi@4: } danielebarchiesi@4: } danielebarchiesi@4: return $pipe; danielebarchiesi@4: } danielebarchiesi@4: danielebarchiesi@4: /** danielebarchiesi@4: * Implements hook_features_export_render() danielebarchiesi@4: */ danielebarchiesi@4: function menu_custom_features_export_render($module, $data) { danielebarchiesi@4: $code = array(); danielebarchiesi@4: $code[] = ' $menus = array();'; danielebarchiesi@4: $code[] = ''; danielebarchiesi@4: danielebarchiesi@4: $translatables = array(); danielebarchiesi@4: foreach ($data as $menu_name) { danielebarchiesi@4: $row = db_select('menu_custom') danielebarchiesi@4: ->fields('menu_custom') danielebarchiesi@4: ->condition('menu_name', $menu_name) danielebarchiesi@4: ->execute() danielebarchiesi@4: ->fetchAssoc(); danielebarchiesi@4: if ($row) { danielebarchiesi@4: $export = features_var_export($row, ' '); danielebarchiesi@4: $code[] = " // Exported menu: {$menu_name}."; danielebarchiesi@4: $code[] = " \$menus['{$menu_name}'] = {$export};"; danielebarchiesi@4: $translatables[] = $row['title']; danielebarchiesi@4: $translatables[] = $row['description']; danielebarchiesi@4: } danielebarchiesi@4: } danielebarchiesi@4: if (!empty($translatables)) { danielebarchiesi@4: $code[] = features_translatables_export($translatables, ' '); danielebarchiesi@4: } danielebarchiesi@4: danielebarchiesi@4: $code[] = ''; danielebarchiesi@4: $code[] = ' return $menus;'; danielebarchiesi@4: $code = implode("\n", $code); danielebarchiesi@4: return array('menu_default_menu_custom' => $code); danielebarchiesi@4: } danielebarchiesi@4: danielebarchiesi@4: /** danielebarchiesi@4: * Implements hook_features_revert(). danielebarchiesi@4: */ danielebarchiesi@4: function menu_custom_features_revert($module) { danielebarchiesi@4: menu_custom_features_rebuild($module); danielebarchiesi@4: } danielebarchiesi@4: danielebarchiesi@4: /** danielebarchiesi@4: * Implements hook_features_rebuild(). danielebarchiesi@4: */ danielebarchiesi@4: function menu_custom_features_rebuild($module) { danielebarchiesi@4: if ($defaults = features_get_default('menu_custom', $module)) { danielebarchiesi@4: foreach ($defaults as $menu) { danielebarchiesi@4: menu_save($menu); danielebarchiesi@4: } danielebarchiesi@4: } danielebarchiesi@4: } danielebarchiesi@4: danielebarchiesi@4: /** danielebarchiesi@4: * Implements hook_features_export_options(). danielebarchiesi@4: */ danielebarchiesi@4: function menu_links_features_export_options() { danielebarchiesi@4: global $menu_admin; danielebarchiesi@4: // Need to set this to TRUE in order to get menu links that the danielebarchiesi@4: // current user may not have access to (i.e. user/login) danielebarchiesi@4: $menu_admin = TRUE; danielebarchiesi@4: $use_menus = array_intersect_key(menu_get_menus(), array_flip(array_filter(variable_get('features_admin_menu_links_menus', array_keys(menu_get_menus()))))); danielebarchiesi@4: $menu_links = menu_parent_options($use_menus, array('mlid' => 0)); danielebarchiesi@4: $options = array(); danielebarchiesi@4: foreach ($menu_links as $key => $name) { danielebarchiesi@4: list($menu_name, $mlid) = explode(':', $key, 2); danielebarchiesi@4: if ($mlid != 0) { danielebarchiesi@4: $link = menu_link_load($mlid); danielebarchiesi@4: $identifier = menu_links_features_identifier($link); danielebarchiesi@4: $options[$identifier] = "{$menu_name}: {$name}"; danielebarchiesi@4: } danielebarchiesi@4: } danielebarchiesi@4: $menu_admin = FALSE; danielebarchiesi@4: return $options; danielebarchiesi@4: } danielebarchiesi@4: danielebarchiesi@4: /** danielebarchiesi@4: * Callback for generating the menu link exportable identifier. danielebarchiesi@4: */ danielebarchiesi@4: function menu_links_features_identifier($link) { danielebarchiesi@4: return isset($link['menu_name'], $link['link_path']) ? "{$link['menu_name']}:{$link['link_path']}" : FALSE; danielebarchiesi@4: } danielebarchiesi@4: danielebarchiesi@4: /** danielebarchiesi@4: * Implements hook_features_export(). danielebarchiesi@4: */ danielebarchiesi@4: function menu_links_features_export($data, &$export, $module_name = '') { danielebarchiesi@4: // Default hooks are provided by the feature module so we need to add danielebarchiesi@4: // it as a dependency. danielebarchiesi@4: $export['dependencies']['features'] = 'features'; danielebarchiesi@4: $export['dependencies']['menu'] = 'menu'; danielebarchiesi@4: danielebarchiesi@4: // Collect a link to module map danielebarchiesi@4: $pipe = array(); danielebarchiesi@4: $map = features_get_default_map('menu_links', 'menu_links_features_identifier'); danielebarchiesi@4: foreach ($data as $identifier) { danielebarchiesi@4: if ($link = features_menu_link_load($identifier)) { danielebarchiesi@4: // If this link is provided by a different module, add it as a dependency. danielebarchiesi@4: if (isset($map[$identifier]) && $map[$identifier] != $module_name) { danielebarchiesi@4: $export['dependencies'][$map[$identifier]] = $map[$identifier]; danielebarchiesi@4: } danielebarchiesi@4: else { danielebarchiesi@4: $export['features']['menu_links'][$identifier] = $identifier; danielebarchiesi@4: } danielebarchiesi@4: // For now, exclude a variety of common menus from automatic export. danielebarchiesi@4: // They may still be explicitly included in a Feature if the builder danielebarchiesi@4: // chooses to do so. danielebarchiesi@4: if (!in_array($link['menu_name'], array('features', 'primary-links', 'secondary-links', 'navigation', 'admin', 'devel'))) { danielebarchiesi@4: $pipe['menu_custom'][] = $link['menu_name']; danielebarchiesi@4: } danielebarchiesi@4: } danielebarchiesi@4: } danielebarchiesi@4: return $pipe; danielebarchiesi@4: } danielebarchiesi@4: danielebarchiesi@4: /** danielebarchiesi@4: * Implements hook_features_export_render() danielebarchiesi@4: */ danielebarchiesi@4: function menu_links_features_export_render($module, $data) { danielebarchiesi@4: $code = array(); danielebarchiesi@4: $code[] = ' $menu_links = array();'; danielebarchiesi@4: $code[] = ''; danielebarchiesi@4: danielebarchiesi@4: $translatables = array(); danielebarchiesi@4: foreach ($data as $identifier) { danielebarchiesi@4: if ($link = features_menu_link_load($identifier)) { danielebarchiesi@4: // Replace plid with a parent path. danielebarchiesi@4: if (!empty($link['plid']) && $parent = menu_link_load($link['plid'])) { danielebarchiesi@4: $link['parent_path'] = $parent['link_path']; danielebarchiesi@4: } danielebarchiesi@4: unset($link['plid']); danielebarchiesi@4: unset($link['mlid']); danielebarchiesi@4: danielebarchiesi@4: $code[] = " // Exported menu link: {$identifier}"; danielebarchiesi@4: $code[] = " \$menu_links['{$identifier}'] = ". features_var_export($link, ' ') .";"; danielebarchiesi@4: $translatables[] = $link['link_title']; danielebarchiesi@4: } danielebarchiesi@4: } danielebarchiesi@4: if (!empty($translatables)) { danielebarchiesi@4: $code[] = features_translatables_export($translatables, ' '); danielebarchiesi@4: } danielebarchiesi@4: danielebarchiesi@4: $code[] = ''; danielebarchiesi@4: $code[] = ' return $menu_links;'; danielebarchiesi@4: $code = implode("\n", $code); danielebarchiesi@4: return array('menu_default_menu_links' => $code); danielebarchiesi@4: } danielebarchiesi@4: danielebarchiesi@4: /** danielebarchiesi@4: * Implements hook_features_revert(). danielebarchiesi@4: */ danielebarchiesi@4: function menu_links_features_revert($module) { danielebarchiesi@4: menu_links_features_rebuild($module); danielebarchiesi@4: } danielebarchiesi@4: danielebarchiesi@4: /** danielebarchiesi@4: * Implements hook_features_rebuild(). danielebarchiesi@4: */ danielebarchiesi@4: function menu_links_features_rebuild($module) { danielebarchiesi@4: if ($menu_links = features_get_default('menu_links', $module)) { danielebarchiesi@4: menu_links_features_rebuild_ordered($menu_links); danielebarchiesi@4: } danielebarchiesi@4: } danielebarchiesi@4: danielebarchiesi@4: /** danielebarchiesi@4: * Generate a depth tree of all menu links. danielebarchiesi@4: */ danielebarchiesi@4: function menu_links_features_rebuild_ordered($menu_links, $reset = FALSE) { danielebarchiesi@4: static $ordered; danielebarchiesi@4: static $all_links; danielebarchiesi@4: if (!isset($ordered) || $reset) { danielebarchiesi@4: $ordered = array(); danielebarchiesi@4: $unordered = features_get_default('menu_links'); danielebarchiesi@4: danielebarchiesi@4: // Order all links by depth. danielebarchiesi@4: if ($unordered) { danielebarchiesi@4: do { danielebarchiesi@4: $current = count($unordered); danielebarchiesi@4: foreach ($unordered as $key => $link) { danielebarchiesi@4: $identifier = menu_links_features_identifier($link); danielebarchiesi@4: $parent = isset($link['parent_path']) ? "{$link['menu_name']}:{$link['parent_path']}" : ''; danielebarchiesi@4: if (empty($parent)) { danielebarchiesi@4: $ordered[$identifier] = 0; danielebarchiesi@4: $all_links[$identifier] = $link; danielebarchiesi@4: unset($unordered[$key]); danielebarchiesi@4: } danielebarchiesi@4: elseif (isset($ordered[$parent])) { danielebarchiesi@4: $ordered[$identifier] = $ordered[$parent] + 1; danielebarchiesi@4: $all_links[$identifier] = $link; danielebarchiesi@4: unset($unordered[$key]); danielebarchiesi@4: } danielebarchiesi@4: } danielebarchiesi@4: } while (count($unordered) < $current); danielebarchiesi@4: } danielebarchiesi@4: asort($ordered); danielebarchiesi@4: } danielebarchiesi@4: danielebarchiesi@4: // Ensure any default menu items that do not exist are created. danielebarchiesi@4: foreach (array_keys($ordered) as $identifier) { danielebarchiesi@4: $link = $all_links[$identifier]; danielebarchiesi@4: $existing = features_menu_link_load($identifier); danielebarchiesi@4: if (!$existing || in_array($link, $menu_links)) { danielebarchiesi@4: // Retrieve the mlid if this is an existing item. danielebarchiesi@4: if ($existing) { danielebarchiesi@4: $link['mlid'] = $existing['mlid']; danielebarchiesi@4: } danielebarchiesi@4: // Retrieve the plid for a parent link. danielebarchiesi@4: if (!empty($link['parent_path']) && $parent = features_menu_link_load("{$link['menu_name']}:{$link['parent_path']}")) { danielebarchiesi@4: $link['plid'] = $parent['mlid']; danielebarchiesi@4: } danielebarchiesi@4: else { danielebarchiesi@4: $link['plid'] = 0; danielebarchiesi@4: } danielebarchiesi@4: menu_link_save($link); danielebarchiesi@4: } danielebarchiesi@4: } danielebarchiesi@4: } danielebarchiesi@4: danielebarchiesi@4: /** danielebarchiesi@4: * Load a menu link by its menu_name:link_path identifier. danielebarchiesi@4: */ danielebarchiesi@4: function features_menu_link_load($identifier) { danielebarchiesi@4: list($menu_name, $link_path) = explode(':', $identifier, 2); danielebarchiesi@4: $link = db_select('menu_links') danielebarchiesi@4: ->fields('menu_links', array('menu_name', 'mlid', 'plid', 'link_path', 'router_path', 'link_title', 'options', 'module', 'hidden', 'external', 'has_children', 'expanded', 'weight')) danielebarchiesi@4: ->condition('menu_name', $menu_name) danielebarchiesi@4: ->condition('link_path', $link_path) danielebarchiesi@4: ->addTag('features_menu_link') danielebarchiesi@4: ->execute() danielebarchiesi@4: ->fetchAssoc(); danielebarchiesi@4: if ($link) { danielebarchiesi@4: $link['options'] = unserialize($link['options']); danielebarchiesi@4: return $link; danielebarchiesi@4: } danielebarchiesi@4: return FALSE; danielebarchiesi@4: }