0

Is there a way to get Drupal internal path from the external URL? I need to get node id (or any other internal path) from the URL that user specifies in the textfield. External URL in this case is not the URL of current page, it is arbitrary URL that is entered by user.

For example:

Base URL: http://www.example.com/drupal

Alias of node/101: foo/bar

User input: http://www.example.com/drupal/foo/bar or http://www.example.com/drupal/?q=foo/bar

Expected result: node/101 or foo/bar

The problem explained:

  1. drupal_get_normal_path() only returns normal path if internal alias is given. In this case internal alias from external URL needs to be extracted but there are no internal Drupal function that would do that directly.

  2. If site has Clean URLs enabled, request path in external URL can either be in "q" argument (?q=foo/bar) or in URL itself (/drupal/foo/bar).

  • are you familiar with drupal_get_normal_path()? if not, it in combination with PHP's parse_url() function will probably do what you are hoping, assuming, of course, the base URL is the local system. There is little way to ask a remote system this. – Jimajamma Aug 13 '13 at 14:35
  • PHP's parse_url() function will do that extraction for you. – Jimajamma Aug 13 '13 at 14:45
2

Dull Ax....

$path='';
$with_trailing_slash=$base_url . '/';

if (strpos($user_input, $with_trailing_slash)===0) {
  $user_input=str_replace($with_trailing_slash, '', $user_input);
  if (strpos($user_input, '?q=')===0) {
    $path=substr($user_input, 3);
  } else {
    $path=$user_input;
  }
} else {
  // this isn't on the local system so there is no way to figure it out
}

if ($path) {
  $normal=drupal_get_normal_path($path);
}
2

I came up with the following code, based on a great @Jimajamma answer.

/**
 * Returns internal path, query and fragment from external URL
 */
function get_path_from_url($url, $normal_path = TRUE) {
  global $base_path;
  // Get hostname
  preg_match("/^(https?:\/\/)?([^\/]+)/i", $url, $domain);
  // Format localhost + base_path (http://hostname/drupalbase)
  $base = (isset($domain[0]) ? $domain[0] : '') . $base_path;
  // If $url contains $base, remove the $base part
  if (strpos($url, $base) === 0) {
    $path = str_replace($base, '', $url);
  }
  // $url is presumed to be without $base part (internal path?)
  else {
    $path = $url;
  }
  // Path may contain language prefix. Check if that is the case.
  list($language, $path) = language_url_split_prefix($path, language_list());
  // Parse the path (without $base)
  $result = drupal_parse_url($path);
  // Add language to result
  if (!empty($language)) {
    $result['language'] = $language;
  }
  // Get normal path
  if ($normal_path) {
    $result['path'] = drupal_get_normal_path($result['path']);
  }

  return $result;
}

The following function will take both clean URLs and regular URLs (with internal path in ?q=), http or https protocol.

Any of these URLs will be converted to internal path (or alias) if processed on a host www.example.com with site locating in /drupal/:

$url = 'https://www.example.com/drupal/en/node/b10d6840?foo=bar#xyz';
$url = 'https://www.example.com/drupal/en/node/b10d6840?foo=bar#xyz';
$url = 'http://www.example.com/drupal?q=en/node/b10d6840&foo=bar#xyz';
$url = '?q=en/node/b10d6840&foo=bar#xyz';
$url = 'en/node/b10d6840?foo=bar#xyz';

get_path_from_url($url) will return:

array(
    'path' => 'node/110',
    'query' => array(
        'foo' => 'bar',
    ),
    'fragment' => 'xyz',
    'language' => [language object],
);

get_path_from_url($url, FALSE) will return aliased path:

array(
    'path' => 'node/b10d6840',
    'query' => array(
        'foo' => 'bar',
    ),
    'fragment' => 'xyz',
    'language' => [language object],
);
1

Since I don't know in what context you're going to be using this in, so I'll just point you to the Drupal function which can generate the internal path when given a URL alias: drupal_get_normal_path

drupal_get_normal_path: Given a path alias, return the internal path it represents.

  • 1
    As explained in the question, I need to get internal path (normal path) or internal alias from external URL therefore drupal_get_normal_path does not address the problem directly as internal alias need to be known first. – maijs Aug 13 '13 at 14:45

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.