<?php

/**
 * @file
 *
 * MultiLink Redirect module for Drupal 7.
 * Support: Commercial support and customization is available from www.netgenius.co.uk
 * Contact: www.netgenius.co.uk/contact or email drupal at netgenius.co.uk
 */

/**
 * Implements hook_permission().
 */
function multilink_redirect_permission() {
  return array(
    'administer multilink redirect' => array(
      'title' => t('Administer MultiLink Redirect'),
      'description' => t('Configure the MultiLink Redirect module.'),
    ),
    'bypass multilink redirect' => array(
      'title' => t('Bypass MultiLink Redirect'),
      'description' => t('See a message showing the redirect target URL without actually being redirected.'),
    ),
    'bypass multilink redirect silent' => array(
      'title' => t('Hide the redirect message.'),
      'description' => t('Hide the message which is otherwise shown when redirect is bypassed.'),
    ),
  );
}

/*
 * Check if path is node/nid and return nid or FALSE.
 */
function multilink_redirect_node($path) {
  $pattern = '!^node/([1-9]\d*)/?$!';
  $ret = (preg_match($pattern, $path, $matches) != 0)? $matches[1] : FALSE;
  ////multilink_set_message('matches: ' . print_r($matches, 1));
  return $ret;
}

/*
 * Return the full path *actually requested*, including protocol but without query string.
 */
function multilink_redirect_qpath() {
  //See: http://php.net/manual/en/reserved.variables.server.php
  $http = (empty($_SERVER['HTTPS']) || $_SERVER['HTTPS'] == 'off')? 'http' : 'https';
  $path = parse_url(request_uri(), PHP_URL_PATH);
  $fmt = variable_get('clean_url', 0)? '%s://%s%s' : '%s://%s?q=%s';
  $result = sprintf($fmt, $http, $_SERVER['HTTP_HOST'], $path);
  //drupal_set_message('qpath: ' . $result);
  return $result;
}

/*
 * Implements hook_init().
 */
function multilink_redirect_init() {
  // Call the main process.
  _multilink_redirect_main();
}

/*
 * Main processing - may also be called during boot from multilink_redirect_cached_boot().
 * Test if redirect is needed and if so exit via drupal_goto().
 */
function _multilink_redirect_main() {
  // Get the internal path to front-page.
  // @todo Handle when site_frontpage is using an alias (not normally the case.))
  $front = variable_get('site_frontpage', 'node');

  // Get requested internal path (without language prefix).
  $path = $_GET['q']? $_GET['q'] : $front;

  // If path matches one of the configured ignore_paths, exit now.
  $ignore_paths = variable_get('multilink_redirect_ignore');
  if (!empty($ignore_paths) && drupal_match_path($path, $ignore_paths)) {
    return;
  }

  // Make sure MultiLink is initialised.
  multilink_init();

  // If this is a node/123 path, get Multilink's target path.
  if ($nid = multilink_redirect_node($path)) {
    $link = _multilink_getnode($nid);
    // Use new path if node found, otherwise keep original path.
    $rpath = $link? 'node/' . $link->nid : $path;
  }
  // Otherwise this is a not a node/123 path so don't change it.
  else {
    $rpath = $path;
  }

  // If $rpath is actually the front-page, use an empty path instead.
  if ($rpath == $front)  {
    $rpath = '';
  }

  // Get the actually requested full path including protocol.
  $qpath = multilink_redirect_qpath();

  // Get final target url for any redirect.
  // Note: multilink_url() uses url() which gets the most recently added alias (if more than one.)
  // Note: multilink_url() is fast because url() is fast - no significant gain with (standard) caching.
  $rpath = multilink_url($rpath, TRUE);

  // If requested and target urls are different then we need to redirect.
  // Note use rawurldecode to double-check, in case of any weird characters in request.
  if ($rpath != $qpath && rawurldecode($rpath) != $qpath) {

    // Only redirect if $_POST is empty, processing index.php and not under Drush [#1278930]
    if (empty($_POST) && $_SERVER['SCRIPT_NAME'] == $GLOBALS ['base_path'] . 'index.php' && !function_exists('drush_main')) {
      // Fix some compatibility issues when SecurePages is active.
      if (function_exists('multilink_securepages_redirect_fix')) {
        multilink_securepages_redirect_fix($rpath);
      }

      // Get the Query String (minus the 'q').
      $get = $_GET; unset($get['q']);

      // Bypass the redirect if user has permission.
      $bypass = 'bypass multilink redirect';
      if (function_exists('user_access') && user_access($bypass)) {
        // Display a message unless user has "silent" permission or uid==1.
        if (!user_access('bypass multilink redirect silent') || $GLOBALS['user']->uid == 1) {
          $url = url($rpath, array('query' => $get));
          $tvars = array(
            '%module' => 'MultiLink Redirect',
            '!from' => sprintf('<b>%s</b>', check_url($qpath)),
            '!link' => sprintf('<b>%s</b>', l($url, $rpath, array('query' => $get))),
            '%perm' => $bypass,
          );

          $msg = '%module: redirect from !from to !link not done to %perm permission.';
          drupal_set_message(t($msg, $tvars), 'warning');
        }
      }
      // Else, do the redirect.
      else {
        drupal_goto($rpath, $get, NULL, 302);
      }
    }
  }
}

/*
 * Implment hook_menu for the admin form.
 */
function multilink_redirect_menu() {

  $items = array(
    'admin/config/regional/multilink_redirect' => array(
      'title' => 'MultiLink Redirect',
      'description' => 'Configure MultiLink Redirect',
      'page callback' => 'drupal_get_form',
      'page arguments' => array('multilink_redirect_admin'),
      'access arguments' => array('administer multilink redirect'),
      'type' => MENU_NORMAL_ITEM,
     ),
  );
  return $items;
}

// Admin form.
function multilink_redirect_admin() {
  $tvars = array(
    '%example' => 'sites/*/files/styles/*',
  );

  $form = array(
    'multilink_redirect_ignore' => array(
      '#type' => 'textarea',
      '#title' => t('Paths to ignore'),
      '#default_value' => variable_get('multilink_redirect_ignore'),
      '#description' => t('Here you can define any paths which should never be redirected. Enter one path per line. Example: %example', $tvars),
    ),
  );
  return system_settings_form($form);
}

// --- Drupal docs advise NOT closing PHP tags ---
