2

I'm working on a module that accepts user-specified paths for special treatment. I want to have a validation step where I check whether that path actually exists on the site.

Is doing a query to the menu_router table sufficient? Is there a better way -- say, a Drupal function -- to validate a url?

1 Answer 1

4

Looking at the code for menu_edit_item_validate(), which is the function that validates the input from the user when creating a new menu item, you will notice it calls drupal_valid_path(). If that function is not enough, you could look at the code of menu_edit_item_validate() to see if that code can be useful to create your own validation function.

  $normal_path = drupal_get_normal_path($item['link_path']);
  if ($item['link_path'] != $normal_path) {
    drupal_set_message(t('The menu system stores system paths only, but will use the URL alias for display. %link_path has been stored as %normal_path', array('%link_path' => $item['link_path'], '%normal_path' => $normal_path)));
    $item['link_path'] = $normal_path;
  }
  if (!url_is_external($item['link_path'])) {
    $parsed_link = parse_url($item['link_path']);
    if (isset($parsed_link['query'])) {
      $item['options']['query'] = drupal_get_query_array($parsed_link['query']);
    }
    else {
      // Use unset() rather than setting to empty string
      // to avoid redundant serialized data being stored.
      unset($item['options']['query']);
    }
    if (isset($parsed_link['fragment'])) {
      $item['options']['fragment'] = $parsed_link['fragment'];
    }
    else {
      unset($item['options']['fragment']);
    }
    if ($item['link_path'] != $parsed_link['path']) {
      $item['link_path'] = $parsed_link['path'];
    }
  }
  if (!trim($item['link_path']) || !drupal_valid_path($item['link_path'], TRUE)) {
    form_set_error('link_path', t("The path '@link_path' is either invalid or you do not have access to it.", array('@link_path' => $item['link_path'])));
  }

If you need to verify if the anonymous user has access to the menu item, you can use code similar to the following one:

drupal_save_session(FALSE);
$original_user = $GLOBALS['user'];
$GLOBALS['user'] = drupal_anonymous_user();

$result = drupal_valid_path($link, TRUE);

$GLOBALS['user'] = $original_user;
drupal_save_session(TRUE);

To change the code I shown from menu_edit_item_validate(), you should rewrite the last control statement as the following code.

  drupal_save_session(FALSE);
  $original_user = $GLOBALS['user'];
  $GLOBALS['user'] = drupal_anonymous_user();

  if (!trim($item['link_path']) || !drupal_valid_path($item['link_path'], TRUE)) {
    form_set_error('link_path', t("The path '@link_path' is either invalid or you do not have access to it.", array('@link_path' => $item['link_path'])));
  }

  $GLOBALS['user'] = $original_user;
  drupal_save_session(TRUE);

This is the only possibility you have, if you don't want to rewrite all the code Drupal uses to verify if a user has access to a menu item, as that code verifies the currently logged-in user has access to the menu item, not a user for which the user object is passed to the code.

4
  • drupal_valid_path() won't work for my purposes because the documentation says it checks if the current user has access to it. In my case, a person with administrative rights will be setting things up for anonymous users. So it looks like I will be drawing from this function.
    – user1359
    Feb 6, 2012 at 23:49
  • 2
    See the updated answer.
    – apaderno
    Feb 7, 2012 at 0:33
  • Actually, I need to validate some urls that are not accessible by the anonymous user, but nonetheless exist. So it looks like I will be re-writing the function... :P
    – user1359
    Feb 7, 2012 at 15:20
  • Thanks. It's work for me too! I trusted that drupal_valid_path() validates node path, but it doesn't and I didn't look into drupal_valid_path(). Anyway, thanks! Feb 10, 2012 at 11:24

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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