You are here

function entity_translation_menu_alter in Entity Translation 7

Implements hook_menu_alter().

File

./entity_translation.module, line 378

Code

function entity_translation_menu_alter(&$items) {
  $backup = array();

  // Initialize path schemes validation function with set of current menu items.
  $_null = NULL;
  _entity_translation_validate_path_schemes($_null, FALSE, $items);

  // Create tabs for all possible entity types.
  foreach (entity_get_info() as $entity_type => $info) {

    // Menu is rebuilt while determining entity translation base paths and
    // callbacks so we might not have them available yet.
    if (entity_translation_enabled($entity_type)) {
      $et_info = $info['translation']['entity_translation'];

      // Flag for tracking whether we have managed to attach the translate UI
      // successfully at least once.
      $translate_ui_attached = FALSE;

      // Validate path schemes for current entity type. Also removes invalid
      // ones and adds '... path parts' elements.
      _entity_translation_validate_path_schemes($et_info['path schemes'], $info['label'], FALSE, TRUE);
      foreach ($et_info['path schemes'] as $scheme) {
        $translate_item = NULL;
        $edit_item = NULL;

        // If we have a translate path then attach the translation UI, and
        // register the callback for deleting a translation.
        if (isset($scheme['translate path'])) {
          $translate_path = $scheme['translate path'];
          $keys = array(
            'theme callback',
            'theme arguments',
            'access callback',
            'access arguments',
            'load arguments',
          );
          $item = array_intersect_key($info['translation']['entity_translation'], drupal_map_assoc($keys));
          $item += array(
            'file' => 'entity_translation.admin.inc',
            'module' => 'entity_translation',
          );
          $entity_position = array_search($scheme['path wildcard'], $scheme['translate path parts']);
          if ($item['access callback'] == 'entity_translation_tab_access') {
            $item['access arguments'][] = $entity_position;
          }

          // Backup existing values for the translate overview page.
          if (isset($items[$translate_path])) {
            $backup[$entity_type] = $items[$translate_path];
          }
          $items[$translate_path] = array(
            'title' => 'Translate',
            'page callback' => 'entity_translation_overview',
            'page arguments' => array(
              $entity_type,
              $entity_position,
            ),
            'type' => MENU_LOCAL_TASK,
            'weight' => 2,
            'context' => MENU_CONTEXT_PAGE | MENU_CONTEXT_INLINE,
          ) + $item;

          // Delete translation callback.
          $language_position = count($scheme['translate path parts']) + 1;
          $items["{$translate_path}/delete/%entity_translation_language"] = array(
            'title' => 'Delete',
            'page callback' => 'drupal_get_form',
            'page arguments' => array(
              'entity_translation_delete_confirm',
              $entity_type,
              $entity_position,
              $language_position,
            ),
          ) + $item;
          $translate_item =& $items[$translate_path];
        }

        // If we have an edit path, then replace the menu edit form with our
        // proxy implementation, and register new callbacks for adding and
        // editing a translation.
        if (isset($scheme['edit path'])) {

          // Find the edit item. If the edit path is a default local task we
          // need to find the parent item.
          $real_edit_path_parts = $scheme['real edit path parts'];
          do {
            $edit_item =& $items[implode('/', $real_edit_path_parts)];
            array_pop($real_edit_path_parts);
          } while (!empty($edit_item['type']) && $edit_item['type'] == MENU_DEFAULT_LOCAL_TASK);
          $edit_path = $scheme['edit path'];
          $edit_path_parts = $scheme['edit path parts'];

          // Replace the main edit callback with our proxy implementation to set
          // form language to the current language and check access.
          $entity_position = array_search($scheme['path wildcard'], $edit_path_parts);

          // Make sure incoming page and access arguments are arrays.
          $original_item = $edit_item + array(
            'page arguments' => array(),
            'access arguments' => array(),
          );
          $args = array(
            $entity_type,
            $entity_position,
            FALSE,
            $original_item,
          );
          $edit_item['page callback'] = 'entity_translation_edit_page';
          $edit_item['page arguments'] = array_merge($args, $original_item['page arguments']);
          $edit_item['access callback'] = 'entity_translation_edit_access';
          $edit_item['access arguments'] = array_merge($args, $original_item['access arguments']);

          // Edit translation callback.
          if ($scheme['edit tabs'] !== FALSE) {
            $translation_position = count($edit_path_parts);
            $args = array(
              $entity_type,
              $entity_position,
              $translation_position,
              $original_item,
            );
            $items["{$edit_path}/%entity_translation_language"] = array(
              'type' => MENU_DEFAULT_LOCAL_TASK,
              'title callback' => 'entity_translation_edit_title',
              'title arguments' => array(
                $translation_position,
              ),
              'page callback' => 'entity_translation_edit_page',
              'page arguments' => array_merge($args, $original_item['page arguments']),
              'access callback' => 'entity_translation_edit_access',
              'access arguments' => array_merge($args, $original_item['access arguments']),
            ) + $original_item;
          }

          // Add translation callback.
          $add_path = "{$edit_path}/add/%entity_translation_language/%entity_translation_language";
          $source_position = count($edit_path_parts) + 1;
          $target_position = count($edit_path_parts) + 2;
          $args = array(
            $entity_type,
            $entity_position,
            $source_position,
            $target_position,
            $original_item,
          );
          $items[$add_path] = array(
            'title callback' => 'Add translation',
            'page callback' => 'entity_translation_add_page',
            'page arguments' => array_merge($args, $original_item['page arguments']),
            'type' => MENU_LOCAL_TASK,
            'access callback' => 'entity_translation_add_access',
            'access arguments' => array_merge($args, $original_item['access arguments']),
          ) + $original_item;
        }

        // Make the "Translate" tab follow the "Edit" tab if possible.
        if ($translate_item && $edit_item && isset($edit_item['weight'])) {
          $translate_item['weight'] = $edit_item['weight'] + 1;
        }

        // If we have both an edit item and a translate item, then we know that
        // the translate UI has been attached properly (at least once).
        $translate_ui_attached = $translate_ui_attached || $translate_item && $edit_item;

        // Cleanup reference variables, so we don't accidentially overwrite
        // something in a later iteration.
        unset($translate_item, $edit_item);
      }
      if ($translate_ui_attached == FALSE) {
        watchdog('entity_translation', 'The entities of type %entity_type do not define a valid path scheme: it will not be possible to translate them.', array(
          '%entity_type' => $info['label'],
        ));
      }

      // Entity-type-specific menu alterations.
      $function = 'entity_translation_' . $entity_type . '_menu_alter';
      if (function_exists($function)) {
        $function($items, $backup);
      }
    }
  }

  // Avoid bloating memory with unused data.
  drupal_static_reset('_entity_translation_validate_path_schemes');
}