7.x common.inc entity_uri($entity_type, $entity)

Returns the URI elements of an entity.

Parameters

$entity_type: The entity type; e.g. 'node' or 'user'.

$entity: The entity for which to generate a path.

Return value

An array containing the 'path' and 'options' keys used to build the URI of the entity, and matching the signature of url(). NULL if the entity has no URI of its own.

13 calls to entity_uri()
image_field_formatter_view in modules/image/image.field.inc
Implements hook_field_formatter_view().
node_admin_nodes in modules/node/node.admin.inc
Form builder: Builds the node administration overview.
node_page_view in modules/node/node.module
Menu callback: Displays a single node.
node_search_execute in modules/node/node.module
Implements hook_search_execute().
rdf_preprocess_comment in modules/rdf/rdf.module
Implements MODULE_preprocess_HOOK().

... See full list

File

includes/common.inc, line 8156
Common functions that many Drupal modules will need to reference.

Code

function entity_uri($entity_type, $entity) {
  $info = entity_get_info($entity_type);
  list($id, $vid, $bundle) = entity_extract_ids($entity_type, $entity);

  // A bundle-specific callback takes precedence over the generic one for the
  // entity type.
  if (isset($info['bundles'][$bundle]['uri callback'])) {
    $uri_callback = $info['bundles'][$bundle]['uri callback'];
  }
  elseif (isset($info['uri callback'])) {
    $uri_callback = $info['uri callback'];
  }
  else {
    return NULL;
  }

  // Invoke the callback to get the URI. If there is no callback, return NULL.
  if (isset($uri_callback) && function_exists($uri_callback)) {
    $uri = $uri_callback($entity);
    // Pass the entity data to url() so that alter functions do not need to
    // lookup this entity again.
    $uri['options']['entity_type'] = $entity_type;
    $uri['options']['entity'] = $entity;
    return $uri;
  }
}

Comments

natemow’s picture

My requirement: The full node view of some sidebar teasers should link to the referenced parent node's MENU_LOCAL_TASK tab callback and be rendered directly there; users should not be sent to the sidebar node's full page view...we only want them viewing content in the context of the referenced parent node.

My solution: This could have been accomplished several different ways, but I decided to create hook_entity_uri_alter in my custom module. All of the referenced nodes are passed through template_preprocess_node anyway, and I just wanted a repeatable pattern for updating $node_url in my theme's node.tpl.php from other custom mods.

The hook_entity_uri_alter function as defined in mymodule.api.php:

function hook_entity_uri_alter($entity_type, $entity) {
  return array();
}

My module's implementation of said hook:

function mymodule_entity_uri_alter($entity_type, $entity) {

  $uri = array();

  if ($entity_type == 'node') {
    switch ($entity->type) {
      case 'forum':
        // In this example, we're returning an alternate $uri['path']
        // based on a forum node's "field_myfield" value.
        $nid_reference = field_get_items('node', $entity, 'field_myfield');
        $nid_reference = $nid_reference[0]['target_id'];

        $uri['path'] = 'node/' . $nid_reference . '/discussions/' . $entity->nid;
        $uri['options'] = array();

        break;
    }
  }

  return $uri;
}

And the template_preprocess_node implementation (in my case, it's in the module itself, but could just as easily be moved to the theme layer if needed) :

function mymodule_preprocess_node(&$vars) {

  // Invoke entity_uri_alter hooks
  $uri_alter = module_invoke_all('entity_uri_alter', 'node', $vars['node']);
  if (!empty($uri_alter)) {
    $vars['node_url'] = url($uri_alter['path'], $uri_alter['options']);
  }

}

Note for reviewers/maintainers -- I wasn't entirely sure where this should be added, but happy to move over to drupal.org and/or update as needed.

jgraham’s picture

I think a better way to accomplish what you are trying is to implement hook_entity_info_alter() and then change the corresponding 'uri callback' value.

This way the behavior would be overridden universally and not result in inconsistent results.