<?php
/**
 * @file accountmenu.module
 * Provide a dynamic Log in/My account/Log out account menu
 *
 * This module provides a dynamic menu for login, logout and access to my account page.
 * The menu is dynamic such that when he user is not logged in, only the "Log in" link
 * is shown. After the user has logged in, the menu change to "My account" "Log out".
 * The "Log in" link returns to the original page from where the user originally click.
 * This menu defaults to the menu name "Account menu". However, it can be move to
 * any menu at admin/settings/accountmenu.
 *
 */

/**
 * Implements hook_help.
 */
function accountmenu_help($path, $arg) {
  $output = '';
  switch ($path) {
    case 'admin/help#accountmenu':
      $output .= '<p>'. t('Provides a dynamic "Log in|My account|Log out" account menu') .'</p>';
      $output .= '<p>'. t('By default, the links are under the menu "Account menu", they can be <a href="@settings">moved</a> to be part of any menu.', array('@settings' => url('admin/settings/accountmenu'))) .'</p>';
      $output .= '<p>'. t('The Account menu links can be <a href="@customize">customized</a>, the "My account" link title can include the tokens <em>@name</em> or <em>@realname</em>, <em>@name</em> is replaced with the log in name and <em>@realname</em> is replaced with the real name if the <a href="@module-path">RealName module</a> is installed, if not, <em>@realname</em> is replace with the log in name.',
                           array('@customize' => url('admin/build/menu-customize/'. variable_get('accountmenu_menu_name', 'accountmenu')),
                                '@module-path' => url('http://drupal.org/project/realname', array('external' => TRUE)),
                          )) .'</p>';
      $output .= '<p>'. t('The Account menu links are displayed with a <a href="@block">block</a>.',
                           array('@block' => url('admin/build/block'),
                          )) .'</p>';
      break;
  }
  return $output;
}

/**
 * Implements hook_menu.
 */
function accountmenu_menu() {
  $items['admin/config/people/accountmenu'] = array(
    'title' => 'Account menu',
    'description' => 'Configure account menu',
    'page callback' => 'drupal_get_form',
    'page arguments' => array('accountmenu_settings_form'),
    'access arguments' => array('administer site configuration'),
    'type' => MENU_NORMAL_ITEM,
    'file' => 'accountmenu.admin.inc',
  );

  $items['user/self'] = array(
    'title' => 'My Own Account',
    'description' => 'The user\'s own account page.',
    'page callback' => 'accountmenu_myaccount',
    'access callback' => 'accountmenu_self_access',
    'menu_name' => 'accountmenu',
    'type' => MENU_NORMAL_ITEM,
  );

  return $items;
}

/**
 * Returns TRUE if the current user can access
 * his own account page.
 */
function accountmenu_self_access() {
  global $user;

  // Nothing for a NULL user
  if (empty($user)) {
    return FALSE;
  }

  $router_item = menu_get_item('user/' . $user->uid);
  return !empty($router_item['access']);
}

/**
 * Redirect user/self to the user's actual profile page.
 */
function accountmenu_myaccount() {
  global $user;

  drupal_goto('user/' . $user->uid);
}

/**
 * Delete our links before making them again. we are really doing a move
 * but there is no move api call so we delete first and re-create.
 * !!! any menu customization made through the menu module UI are lost.
 */
function _accountmenu_reset_menu() {
  _accountmenu_delete_menu();
  _accountmenu_setup_menu();
  $t = get_t();
  drupal_set_message($t('Account menu has been reset, any menu customization is lost and must be <a href="@customize">customized</a> again.', array('@customize' => url('admin/structure/menu/manage/'. variable_get('accountmenu_menu_name', 'accountmenu')))));
}

/**
 * Remove the menu links managed by accountmenu.
 */
function _accountmenu_delete_menu() {
  $result = db_query("SELECT * FROM {menu_links} WHERE module = 'accountmenu'");
  foreach($result as $link) {
    _menu_delete_item($link);
  }
}

/**
 * Create the menu links managed by accountmenu.
 */
function _accountmenu_setup_menu() {
  $menu_name = variable_get('accountmenu_menu_name', 'accountmenu');

  $item = array(
    'link_title' => 'Login',
    'link_path' => 'user/login',
    'options' => array(
      'alter' => TRUE,
      'attributes' => array(
        'title' => t('Login to the site.'),
        'class' => 'popups-form-reload',
      ),
    ),
    'weight' => 0,
    'menu_name' => $menu_name,
    'module' => 'accountmenu',
    'languange' => 'en',
    'customized' => 1,
  );
  menu_link_save($item);

  $item = array(
    'link_title' => 'Register',
    'link_path' => 'user/register',
    'hidden' => 1,
    'options' => array(
      'alter' => TRUE,
      'attributes' => array(
        'title' => t('Register a new account'),
        'class' => 'popups-form-reload',
      ),
    ),
    'weight' => 0,
    'menu_name' => $menu_name,
    'module' => 'accountmenu',
    'languange' => 'en',
    'customized' => 1,
  );
  menu_link_save($item);

  $item = array(
    'link_title' => 'My account',
    'link_path' => 'user/self',
    'title_callback' => NULL,
    'title_arguments' => NULL,
    'options' => array(
      'alter' => TRUE,
      'attributes' => array('title' => t('View/edit user account.'))
    ),
    'weight' => 0,
    'menu_name' => $menu_name,
    'module' => 'accountmenu',
    'languange' => 'en',
    'customized' => 1,
  );
  menu_link_save($item);

  $item = array(
    'link_title' => 'Logout',
    'link_path' => 'user/logout',
    'weight' => 1,
    'menu_name' => $menu_name,
    'module' => 'accountmenu',
    'languange' => 'en',
    'customized' => 1,
  );
  menu_link_save($item);

  // And clear the cache.
  menu_cache_clear_all();
}

/**
 * Returns TRUE if the path should have a ?destination=path
 * parameter in the HTTP query.
 */
function _accountmenu_menu_need_destination($path) {
  $destination_paths = array(
    'user/login',
    'user/register',
  );
  return in_array($path, $destination_paths);
}

/**
 * Implements hook_link_alter.
 *
 * Ensures links that should have destinations do so, and
 * applies our own @name and @realname tokens.
 */
function accountmenu_translated_menu_link_alter(&$item) {
  if ($item['module'] != 'accountmenu') {
    return;
  }

  if (_accountmenu_menu_need_destination($item['link_path'])) {

    if (_accountmenu_is_404() || arg(0) === 'user') {
      // on a 404 page or any 'user' paths, send user to the front
      $item['localized_options']['query'] = array('destination' => '<front>');
    }
    else {
      $item['localized_options']['query'] = drupal_get_destination();
    }
    // potx will complain here, but line 496 of menu.inc is doing the same so
    $item['title'] = t($item['link_title']);
  }
}

/**
 * Substitue tokens @name and @realname with login name and realname. @realname
 * is same as @name if realname module is not install.
 *
 * @param Array $vars variables array pass in fro core
 *
 * @return Array two element array, element 0 is name, 1 is realname
 *
 */
function accountmenu_preprocess_block(&$vars) {
  if ('accountmenu' == $vars['block']->delta) {
    $token_list = _accountmenu_get_name_and_realname();
    $vars['block']->subject = t($vars['block']->subject, $token_list);
  }
}

/**
 * Apply the @name and @realname tokens to the user/self menu item in a menus
 * embedded in a theme.
 */
function accountmenu_preprocess_links(&$vars) {
  if (array_key_exists('links', $vars)) {
    foreach ($vars['links'] as $key => $link) {
      if ((substr($key, 0, 5) === 'menu-') && ($link['href'] == 'user/self')) {
        $vars['links'][$key]['title'] = t($link['title'], _accountmenu_get_name_and_realname());
      }
    }
  }
}

/**
 * Apply the @name and @realname tokens to the user/self menu item in a menu
 * block
 */
function accountmenu_preprocess_menu_link(&$vars) {
  if ($vars['element']['#href'] == 'user/self') {
    $vars['element']['#title'] = t($vars['element']['#title'], _accountmenu_get_name_and_realname());
  }
}

/**
 * Retrieve the user's name and realname
 *
 * @return a two-element array, first element is the user login name,
 *  the second element is user's real name if the realname module is
 *  installed.  If not, it is the same as the first element.
 */
function _accountmenu_get_name_and_realname() {
  global $user;

  // initialize elements [0] and [1], the second will be set to real name if the
  // realname module is installed
  $result = array(
    '@name' => (empty($user->name)) ? '' : $user->name,
    '@realname' => format_username($user),
  );

  // Allow other modules to muck about with the tokens.
  drupal_alter('accountmenu_name_realname', $result);

  return $result;
}

/**
 * Returns TRUE if the request is going to return 404.
 */
function _accountmenu_is_404() {
  return strpos(drupal_get_http_header('Status'), '404 Not Found') != FALSE;
}

/**
 * Implementation of hook_form_alter.
 */
function accountmenu_form_alter(&$form, $form_state, $form_id) {

  if ($form_id == 'menu_edit_item') {
    if (!empty($form['options']['#value']['accountmenu_link_title'])) {
      $form['link_title']['#default_value'] = $form['options']['#value']['accountmenu_link_title'];
    }

    if ($form['link_path']['#value'] == 'user/self') {
      $form['link_title']['#description'] .= '  The tokens <i>@name</i> (login) and <i>@realname</i> (realname, requires Realname module) are available for this menu item.';
    }
  }
}
