I'm trying to port a website over to Drupal 7. The structure consists of locations which have an entity reference to a region which has an entity reference to a country:


This all seems to work OK. A location node doesn't directly know what country it is in, but it does know what region it's in.

The problem is I want to use the old URL structure:


So far I can get it to work for /region/location (as region is referenced from location) but then I get stuck.

What I'm wondering is there any way to pull these other fields (country / continent) into the node and make them available to pathauto?

If it helps it doesn't really matter what the continent and country are as region & location provide enough info. So a wildcard would be fine.

So, firstly, is this possible with this structure. And if so, how?

Any help greatly appreciated.


I was in a similar boat with a site I was working on recently. Unfortunately, Drupal 7 does not fully support tokens on field entities; see http://drupal.org/node/691078. This is why the "location node" type exists in the location module -- it is easier to define tokens for your locations. However, I did not like the UX for location nodes; I greatly preferred the result that can easily be obtained with cck locations.

Since it was not possible to easily support tokens on cck locations, I instead wrote my own custom token code in my custom module for my site. I did spend quite a few hours trying to do the former first, before giving it up as much too large of an effort.

I'm not sure if you are using the location module, or if you are just defining your own entities that happen to contain locations. The fact that you have your location entities chained together implies that you're using your own entity types. Here's the result I came up with for the location module; you should be able to adapt it for standard entities without much trouble. The code below could probably use some minor improvements; 'und' should be LANGUAGE_NONE, the special-checking for a specific content type is probably unnecessary, etc.; it shouldn't be too hard for you to adapt in some code that resolves your chained entity references to build the tokens you need.

Once you've written your code, it's easy to select your new tokens in pathauto to define your URL structure.

function MYMODULE_token_info() {
  // Because of http://drupal.org/node/691078, we just hack in our own
  // field-based tokens here for now (cough).
  // These tokens are only available for nodes of type MY_CONTENT_TYPE_WITH_LOCATION_FIELD
  $node['field_location_street'] = array(
    'name' => t("Location Street"),
    'description' => t('The street address that a location is located at.'),
  $node['field_location_city'] = array(
    'name' => t("Location City"),
    'description' => t('The city that a location is in.'),
  $node['field_location_province'] = array(
    'name' => t("Location Province"),
    'description' => t('The abbreviation for the province (State) that a location is in.'),
  $node['field_location_province_name'] = array(
    'name' => t("Location Province Name"),
    'description' => t('The full name of the province (State) that a location is in.'),
  $node['field_location_country'] = array(
    'name' => t("Location Country"),
    'description' => t('The country that a location is in.'),
  $node['field_location_country_name'] = array(
    'name' => t("Location Country Name"),
    'description' => t('The full name of the country that a location is in.'),
  $node['field_location_summary'] = array(
    'name' => t("Location Summary"),
    'description' => t('A parenthesized summary of the location (City, State).'),
  return array(
    'tokens' => array('node' => $node),

function MYMODULE_tokens($type, $tokens, array $data = array(), array $options = array()) {
  $replacements = array();
  if ($type == 'node' && !empty($data['node'])) {
    $node = $data['node'];
    $location_field = array();
    if (($node->type == 'MY_CONTENT_TYPE_WITH_LOCATION_FIELD') && (isset($node->field_location['und'][0]))) {
      $location_field = $node->field_location['und'][0];
    if (($node->type == 'MY_CONTENT_TYPE_WITH_NODE_REF_TO_TYPE_WITH_LOCATION_FIELD') && (isset($node->field_event_site['und'][0]))) {
      $location_nid = $node->field_event_site['und'][0]['nid'];
      $location_node = node_load($location_nid);
      if (isset($location_node->field_location['und'][0])) {
        $location_field = $location_node->field_location['und'][0];
    if (!empty($location_field)) {
      $location_field['summary'] = "(" . $location_field['city'] . ", " . $location_field['province'] . ")";
      foreach ($tokens as $name => $original) {
        if (substr($name,0,15) == 'field_location_') {
          // $name is always 'field_location_xxx', so key is 'xxx'.
          $key = substr($name, 15);
          if (isset($location_field[$key])) {
            $replacements[$original] = $location_field[$key];
          else {
            $replacements[$original] = '';
  return $replacements;
  • Hi Greg. Thanks for the reply. I was hoping there was a nice easy solution without having to get under the hood as this is my first Drupal project. I'll probably accept the answer once I've digested what it entails and get my head around that. But it looks like the kind of thing I was imagining. I do use the location module but I don't want to have to put in region / country data here as it would be duplicated . Still, once I get the URLs cracked it's pretty much just theming it up... Thanks – Chris Leather Mar 13 '13 at 9:00
  • I tweeted about this question. We'll see if anyone comes by with a better answer. – greg_1_anderson Mar 13 '13 at 14:44

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.