t('Menu link'), 'controller class' => 'DrupalDefaultEntityController', 'base table' => 'menu_links', 'uri callback' => 'xmlsitemap_menu_menu_link_uri', 'fieldable' => FALSE, 'static cache' => TRUE, 'field cache' => TRUE, 'entity keys' => array( 'id' => 'mlid', 'bundle' => 'menu_name', 'label' => 'link_title', 'revision' => '', ), 'load hook' => NULL, 'view modes' => array(), 'translation' => array(), 'schema_fields_sql' => array( 'base table' => drupal_schema_fields_sql('menu_links'), ), 'xmlsitemap' => array( 'process callback' => 'xmlsitemap_menu_xmlsitemap_process_menu_links', ), 'bundle label' => t('Menu'), 'token type' => 'menu_link', ); foreach (menu_get_menus() as $type => $name) { $info['menu_link']['bundles'][$type] = array( 'label' => $name, 'admin' => array( 'path' => 'admin/structure/menu/manage/%menu/edit', 'bundle argument' => 4, 'real path' => 'admin/structure/menu/manage/' . $type . '/edit', 'access arguments' => array('administer menus'), ), ); } } else { // If the entity type already exists ensure the xmlsitemap is added. $info['menu_link'] += array( 'uri callback' => 'xmlsitemap_menu_menu_link_uri', 'xmlsitemap' => array( 'process callback' => 'xmlsitemap_menu_xmlsitemap_process_menu_links', ), ); if (!isset($info['menu_link']['bundle label'])) { $info['menu_link']['bundle label'] = t('Menu'); } } } /** * Entity URI callback. */ function xmlsitemap_menu_menu_link_uri($menu_item) { return is_array($menu_item) ? $menu_item['href'] : $menu_item->href; } /** * Implements hook_cron(). * * Process old menu links not found in the {xmlsitemap} table. */ function xmlsitemap_menu_cron() { xmlsitemap_menu_xmlsitemap_index_links(xmlsitemap_var('batch_limit')); } /** * Implements hook_xmlsitemap_index_links(). */ function xmlsitemap_menu_xmlsitemap_index_links($limit) { if ($menus = xmlsitemap_get_link_type_enabled_bundles('menu_link')) { $sql = "SELECT ml.mlid FROM {menu_links} ml LEFT JOIN {xmlsitemap} x ON x.type = 'menu' AND ml.mlid = x.id WHERE x.id IS NULL AND ml.menu_name IN (:menus) ORDER BY ml.mlid DESC"; $mlids = db_query_range($sql, 0, $limit, array(':menus' => $menus))->fetchCol(); xmlsitemap_menu_xmlsitemap_process_menu_links($mlids); } } /** * Process menu sitemap links. * * @param array $mlids * An array of menu link IDs. */ function xmlsitemap_menu_xmlsitemap_process_menu_links(array $mlids, array $xmlsitemap = array()) { // Set the global user variable to the anonymous user. xmlsitemap_switch_user(0); foreach ($mlids as $mlid) { $menu_item = menu_link_load($mlid); if (empty($menu_item)) { continue; } if (!empty($xmlsitemap)) { $menu_item['xmlsitemap'] = $xmlsitemap; } $link = xmlsitemap_menu_create_link($menu_item); xmlsitemap_link_save($link, array($link['type'] => $menu_item)); } // Set the global user variable back to the original user. xmlsitemap_restore_user(); } /** * Implements hook_form_FORM_ID_alter(). * * @see menu_edit_menu() * @see xmlsitemap_add_link_bundle_settings() */ function xmlsitemap_menu_form_menu_edit_menu_alter(&$form, $form_state) { $menu = isset($form['menu_name']['#default_value']) ? $form['menu_name']['#default_value'] : ''; module_load_include('inc', 'xmlsitemap', 'xmlsitemap.admin'); xmlsitemap_add_link_bundle_settings($form, $form_state, 'menu_link', $menu); } /** * Example functions. * * Function xmlsitemap_menu_form_menu_overview_form_alter(&$form, $form_state) { * $form['#submit'][] = 'xmlsitemap_menu_menu_overview_form_submit'; * } * * Function xmlsitemap_menu_menu_overview_form_submit($form, $form_state) { * $mlids = array(); * foreach (element_children($form) as $mlid) { * if (isset($form[$mlid]['#item'])) { * $mlids[] = $form[$mlid]['#item']['mlid']; * } * } * xmlsitemap_menu_xmlsitemap_process_menu_links($mlids); * } */ /** * Implements hook_form_FORM_ID_alter(). * * @see menu_edit_item() */ function xmlsitemap_menu_form_menu_edit_item_alter(&$form, $form_state) { $menu_name = $form['parent']['#default_value']; $menu_name = substr($menu_name, 0, strpos($menu_name, ':')); // Add the link options. module_load_include('inc', 'xmlsitemap', 'xmlsitemap.admin'); xmlsitemap_add_form_link_options($form, 'menu_link', $menu_name, $form['mlid']['#value']); $form['xmlsitemap']['#weight'] = 30; } /** * Implements hook_menu_insert(). */ function xmlsitemap_menu_menu_insert(array $menu) { if (isset($menu['xmlsitemap'])) { xmlsitemap_link_bundle_settings_save('menu_link', $menu['menu_name'], $menu['xmlsitemap']); } // When menus change, the bundles we defined in // xmlsitemap_menu_entity_info_alter() change, so we need to clear the cache. entity_info_cache_clear(); } /** * Implements hook_menu_update(). */ function xmlsitemap_menu_menu_update(array $menu) { if (isset($menu['xmlsitemap'])) { xmlsitemap_link_bundle_settings_save('menu_link', $menu['menu_name'], $menu['xmlsitemap']); } // When menus change, the bundles we defined in // xmlsitemap_menu_entity_info_alter() change, so we need to clear the cache. entity_info_cache_clear(); } /** * Implements hook_menu_delete(). */ function xmlsitemap_menu_menu_delete(array $menu) { xmlsitemap_link_bundle_delete('menu_link', $menu['menu_name']); // When menus change, the bundles we defined in // xmlsitemap_menu_entity_info_alter() change, so we need to clear the cache. entity_info_cache_clear(); } /** * Implements hook_menu_link_insert(). */ function xmlsitemap_menu_menu_link_insert(array $link) { $link += array('xmlsitemap' => array()); xmlsitemap_menu_xmlsitemap_process_menu_links(array($link['mlid']), $link['xmlsitemap']); } /** * Implements hook_menu_link_update(). * * @see hook_menu_link_alter() */ function xmlsitemap_menu_menu_link_update(array $link) { // $link += array('xmlsitemap' => array()); // @codingStandardsIgnoreLine // xmlsitemap_menu_xmlsitemap_process_menu_links(array($link['mlid']), $link['xmlsitemap']);. } /** * Implements hook_menu_link_alter(). * * We have to use this hook rather than hook_menu_link_update() because this * hook is not always called if the user does not edit the core menu item * fields. * * @see https://www.drupal.org/node/1013856 */ function xmlsitemap_menu_menu_link_alter(array &$link) { if (!empty($link['mlid'])) { $link += array('xmlsitemap' => array()); xmlsitemap_menu_xmlsitemap_process_menu_links(array($link['mlid']), $link['xmlsitemap']); } } /** * Implements hook_menu_link_delete(). */ function xmlsitemap_menu_menu_link_delete(array $link) { xmlsitemap_link_delete('menu_link', $link['mlid']); } /** * Create a sitemap link from a menu item. * * @param array $menu_item * A loaded menu item. */ function xmlsitemap_menu_create_link(array $menu_item) { if (!isset($menu_item['xmlsitemap'])) { $menu_item['xmlsitemap'] = array(); if ($menu_item['mlid'] && $link = xmlsitemap_link_load('menu_link', $menu_item['mlid'])) { $menu_item['xmlsitemap'] = $link; } } $settings = xmlsitemap_link_bundle_load('menu_link', $menu_item['menu_name']); $menu_item['xmlsitemap'] += array( 'type' => 'menu_link', 'id' => $menu_item['mlid'], 'status' => $settings['status'], 'status_default' => $settings['status'], 'status_override' => 0, 'priority' => $settings['priority'], 'priority_default' => $settings['priority'], 'priority_override' => 0, ); // The following values must always be checked because they are volatile. $menu_item['xmlsitemap']['loc'] = $menu_item['href']; $menu_item['xmlsitemap']['subtype'] = $menu_item['menu_name']; $menu_item['xmlsitemap']['access'] = $menu_item['access'] && !$menu_item['external'] && !$menu_item['hidden']; $menu_item['xmlsitemap']['language'] = isset($menu_item['options']['langcode']) ? $menu_item['options']['langcode'] : LANGUAGE_NONE; // Exclude menu items created for nodes that are added by xmlsitemap_node. if ($menu_item['xmlsitemap']['access'] && $menu_item['router_path'] == 'node/%' && module_exists('xmlsitemap_node')) { $node = node_load(substr($menu_item['link_path'], 5)); if ($node) { if (empty($node->xmlsitemap)) { xmlsitemap_node_create_link($node); } if ($node->xmlsitemap['status'] && $node->xmlsitemap['access']) { $menu_item['xmlsitemap']['status'] = FALSE; } } } return $menu_item['xmlsitemap']; } /** * Calculate the priority of a menu link based on depth and weight. */ function xmlsitemap_menu_calculate_priority(array $menu_item) { $priority = (MENU_MAX_DEPTH - $menu_item['depth'] + 1) / MENU_MAX_DEPTH; $priority -= (50 + $menu_item['weight']) / (100 * (MENU_MAX_DEPTH + 1)); return $priority; } /** * Internal default variables for template_var(). */ function xmlsitemap_menu_variables() { $defaults = array(); $menus = array_keys(menu_get_menus()); foreach ($menus as $menu) { $defaults['xmlsitemap_settings_menu_' . $menu] = array( 'status' => XMLSITEMAP_STATUS_DEFAULT, 'priority' => XMLSITEMAP_PRIORITY_DEFAULT, ); } return $defaults; } /** * Implements hook_features_pipe_COMPONENT_alter(). * * Add variables to exported menus. */ function xmlsitemap_menu_features_pipe_menu_custom_alter(&$pipe, $data, $export) { if (!empty($data)) { foreach ($data as $menu_name) { $pipe['variable'][] = "xmlsitemap_settings_menu_link_{$menu_name}"; } } }