- Patch #699440 by scor, effulgentsia, noahb, catch: add bundle support to entity_uri() callback to remove performance overhead of forum_url_outbound_alter().

merge-requests/26/head
Dries Buytaert 2010-04-06 19:49:03 +00:00
parent c2b1029595
commit ba96cffdb7
9 changed files with 101 additions and 43 deletions

View File

@ -6430,11 +6430,42 @@ function entity_prepare_view($entity_type, $entities) {
* uri of its own.
*/
function entity_uri($entity_type, $entity) {
$info = entity_get_info($entity_type);
if (isset($info['uri callback']) && function_exists($info['uri callback'])) {
return $info['uri callback']($entity) + array('options' => array());
// This check enables the URI of an entity to be easily overridden from what
// the callback for the entity type or bundle would return, and it helps
// minimize performance overhead when entity_uri() is called multiple times
// for the same entity.
if (!isset($entity->uri)) {
$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 {
$uri_callback = NULL;
}
// Invoke the callback to get the URI. If there is no callback, set the
// entity's 'uri' property to FALSE to indicate that it is known to not have
// a URI.
if (isset($uri_callback) && function_exists($uri_callback)) {
$entity->uri = $uri_callback($entity);
if (!isset($entity->uri['options'])) {
$entity->uri['options'] = array();
}
}
else {
$entity->uri = FALSE;
}
}
return $entity->uri ? $entity->uri : NULL;
}
/**
* Invokes entity insert/update hooks.
*

View File

@ -2161,8 +2161,10 @@ function template_preprocess_comment(&$variables) {
$variables['new'] = !empty($comment->new) ? t('new') : '';
$variables['picture'] = theme_get_setting('toggle_comment_user_picture') ? theme('user_picture', array('account' => $comment)) : '';
$variables['signature'] = $comment->signature;
$variables['title'] = l($comment->subject, 'comment/' . $comment->cid, array('fragment' => "comment-$comment->cid"));
$variables['permalink'] = l('#', 'comment/' . $comment->cid, array('fragment' => "comment-$comment->cid"));
$uri = entity_uri('comment', $comment);
$variables['title'] = l($comment->subject, $uri['path'], $uri['options']);
$variables['permalink'] = l('#', $uri['path'], $uri['options']);
// Preprocess fields.
field_attach_preprocess('comment', $comment, $variables['elements'], $variables);

View File

@ -218,6 +218,36 @@ function forum_init() {
drupal_add_css(drupal_get_path('module', 'forum') . '/forum.css');
}
/**
* Implements hook_entity_info_alter().
*/
function forum_entity_info_alter(&$info) {
// Take over URI constuction for taxonomy terms that are forums.
if ($vid = variable_get('forum_nav_vocabulary', 0)) {
// Within hook_entity_info(), we can't invoke entity_load() as that would
// cause infinite recursion, so we call taxonomy_vocabulary_get_names()
// instead of taxonomy_vocabulary_load(). All we need is the machine name
// of $vid, so retrieving and iterating all the vocabulary names is somewhat
// inefficient, but entity info is cached across page requests, and an
// iteration of all vocabularies once per cache clearing isn't a big deal,
// and is done as part of taxonomy_entity_info() anyway.
foreach (taxonomy_vocabulary_get_names() as $machine_name => $vocabulary) {
if ($vid == $vocabulary->vid) {
$info['taxonomy_term']['bundles'][$machine_name]['uri callback'] = 'forum_uri';
}
}
}
}
/**
* Entity URI callback.
*/
function forum_uri($forum) {
return array(
'path' => 'forum/' . $forum->tid,
);
}
/**
* Check whether a content type can be used in a forum.
*
@ -681,18 +711,6 @@ function forum_form($node, $form_state) {
return $form;
}
/**
* Implements hook_url_outbound_alter().
*/
function forum_url_outbound_alter(&$path, &$options, $original_path) {
if (preg_match('!^taxonomy/term/(\d+)!', $path, $matches)) {
$term = taxonomy_term_load($matches[1]);
if ($term && $term->vocabulary_machine_name == 'forums') {
$path = 'forum/' . $matches[1];
}
}
}
/**
* Returns a list of all forums for a given taxonomy id
*

View File

@ -1340,7 +1340,9 @@ function template_preprocess_node(&$variables) {
$variables['date'] = format_date($node->created);
$variables['name'] = theme('username', array('account' => $node));
$variables['node_url'] = url('node/' . $node->nid);
$uri = entity_uri('node', $node);
$variables['node_url'] = url($uri['path'], $uri['options']);
$variables['title'] = check_plain($node->title);
$variables['page'] = node_is_page($node);
@ -1581,8 +1583,9 @@ function node_search_execute($keys = NULL) {
$extra = module_invoke_all('node_search_result', $node);
$uri = entity_uri('node', $node);
$results[] = array(
'link' => url('node/' . $item->sid, array('absolute' => TRUE)),
'link' => url($uri['path'], array_merge($uri['options'], array('absolute' => TRUE))),
'type' => check_plain(node_type_get_name($node)),
'title' => $node->title,
'user' => theme('username', array('account' => $node)),
@ -2500,10 +2503,11 @@ function node_page_default() {
*/
function node_page_view($node) {
drupal_set_title($node->title);
$uri = entity_uri('node', $node);
// Set the node path as the canonical URL to prevent duplicate content.
drupal_add_html_head_link(array('rel' => 'canonical', 'href' => url('node/' . $node->nid)), TRUE);
drupal_add_html_head_link(array('rel' => 'canonical', 'href' => url($uri['path'], $uri['options'])), TRUE);
// Set the non-aliased path as a default shortlink.
drupal_add_html_head_link(array('rel' => 'shortlink', 'href' => url('node/' . $node->nid, array('alias' => TRUE))), TRUE);
drupal_add_html_head_link(array('rel' => 'shortlink', 'href' => url($uri['path'], array_merge($uri['options'], array('alias' => TRUE)))), TRUE);
return node_show($node);
}

View File

@ -534,29 +534,31 @@ function rdf_preprocess_field(&$variables) {
* Implements MODULE_preprocess_HOOK().
*/
function rdf_preprocess_user_profile(&$variables) {
// Adds RDFa markup to the user profile page. Fields displayed in this page
// will automatically describe the user.
$account = $variables['elements']['#account'];
$uri = entity_uri('user', $account);
// Adds RDFa markup to the user profile page. Fields displayed in this page
// will automatically describe the user.
if (!empty($account->rdf_mapping['rdftype'])) {
$variables['attributes_array']['typeof'] = $account->rdf_mapping['rdftype'];
$variables['attributes_array']['about'] = url('user/' . $account->uid);
$variables['attributes_array']['about'] = url($uri['path'], $uri['options']);
}
// Adds the relationship between the sioc:User and the foaf:Person who holds
// the account.
$account_holder_meta = array(
'#tag' => 'meta',
'#attributes' => array(
'about' => url('user/' . $account->uid, array('fragment' => 'me')),
'about' => url($uri['path'], array_merge($uri['options'], array('fragment' => 'me'))),
'typeof' => array('foaf:Person'),
'rel' => array('foaf:account'),
'resource' => url('user/' . $account->uid),
'resource' => url($uri['path'], $uri['options']),
),
);
// Adds the markup for username.
$username_meta = array(
'#tag' => 'meta',
'#attributes' => array(
'about' => url('user/' . $account->uid),
'about' => url($uri['path'], $uri['options']),
'property' => $account->rdf_mapping['name']['predicates'],
'content' => $account->name,
)
@ -629,7 +631,8 @@ function rdf_preprocess_comment(&$variables) {
// Adds RDFa markup to the comment container. The about attribute specifies
// the URI of the resource described within the HTML element, while the
// typeof attribute indicates its RDF type (e.g. sioc:Post, etc.).
$variables['attributes_array']['about'] = url('comment/' . $comment->cid, array('fragment' => 'comment-' . $comment->cid));
$uri = entity_uri('comment', $comment);
$variables['attributes_array']['about'] = url($uri['path'], $uri['options']);
$variables['attributes_array']['typeof'] = $comment->rdf_mapping['rdftype'];
}

View File

@ -177,11 +177,10 @@ class UrlAlterFunctionalTest extends DrupalWebTestCase {
$this->assertUrlInboundAlter("user/$uid", "user/$uid");
$this->assertUrlOutboundAlter("user/$uid", "user/$uid");
// Test that 'forum' is altered to 'community' correctly.
// Test that 'forum' is altered to 'community' correctly, both at the root
// level and for a specific existing forum.
$this->assertUrlInboundAlter('community', 'forum');
$this->assertUrlOutboundAlter('forum', 'community');
// Add a forum to test url altering.
$forum_vid = db_query("SELECT vid FROM {taxonomy_vocabulary} WHERE module = 'forum'")->fetchField();
$tid = db_insert('taxonomy_term_data')
->fields(array(
@ -189,15 +188,8 @@ class UrlAlterFunctionalTest extends DrupalWebTestCase {
'vid' => $forum_vid,
))
->execute();
// Test that a existing forum URL is altered.
$this->assertUrlInboundAlter("community/$tid", "forum/$tid");
$this->assertUrlOutboundAlter("taxonomy/term/$tid", "community/$tid");
// Test that a non-existant forum URL is not altered.
$tid++;
$this->assertUrlInboundAlter("taxonomy/term/$tid", "taxonomy/term/$tid");
$this->assertUrlOutboundAlter("taxonomy/term/$tid", "taxonomy/term/$tid");
$this->assertUrlOutboundAlter("forum/$tid", "community/$tid");
}
/**

View File

@ -99,6 +99,10 @@ function hook_hook_info() {
* bundles machine names, as found in the objects' 'bundle' property
* (defined in the 'entity keys' entry above). Elements:
* - label: The human-readable name of the bundle.
* - uri callback: Same as the 'uri callback' key documented above for the
* entity type, but for the bundle only. When determining the URI of an
* entity, if a 'uri callback' is defined for both the entity type and
* the bundle, the one for the bundle is used.
* - admin: An array of information that allows Field UI pages to attach
* themselves to the existing administration pages for the bundle.
* Elements:

View File

@ -609,7 +609,8 @@ function template_preprocess_taxonomy_term(&$variables) {
$variables['term'] = $variables['elements']['#term'];
$term = $variables['term'];
$variables['term_url'] = url('taxonomy/term/' . $term->tid);
$uri = entity_uri('taxonomy_term', $term);
$variables['term_url'] = url($uri['path'], $uri['options']);
$variables['term_name'] = check_plain($term->name);
$variables['page'] = taxonomy_term_is_page($term);
@ -1207,10 +1208,12 @@ function taxonomy_field_formatter_view($entity_type, $entity, $field, $instance,
case 'taxonomy_term_reference_link':
foreach ($items as $delta => $item) {
$term = $item['taxonomy_term'];
$uri = entity_uri('taxonomy_term', $term);
$element[$delta] = array(
'#type' => 'link',
'#title' => $term->name,
'#href' => 'taxonomy/term/' . $term->tid,
'#href' => $uri['path'],
'#options' => $uri['options'],
);
}
break;

View File

@ -3418,8 +3418,9 @@ function user_register_submit($form, &$form_state) {
$account->password = $pass;
// New administrative account without notification.
$uri = entity_uri('user', $account);
if ($admin && !$notify) {
drupal_set_message(t('Created a new user account for <a href="@url">%name</a>. No e-mail has been sent.', array('@url' => url("user/$account->uid"), '%name' => $account->name)));
drupal_set_message(t('Created a new user account for <a href="@url">%name</a>. No e-mail has been sent.', array('@url' => url($uri['path'], $uri['options']), '%name' => $account->name)));
}
// No e-mail verification required; log in user immediately.
elseif (!$admin && !variable_get('user_email_verification', TRUE) && $account->status) {
@ -3434,7 +3435,7 @@ function user_register_submit($form, &$form_state) {
$op = $notify ? 'register_admin_created' : 'register_no_approval_required';
_user_mail_notify($op, $account);
if ($notify) {
drupal_set_message(t('A welcome message with further instructions has been e-mailed to the new user <a href="@url">%name</a>.', array('@url' => url("user/$account->uid"), '%name' => $account->name)));
drupal_set_message(t('A welcome message with further instructions has been e-mailed to the new user <a href="@url">%name</a>.', array('@url' => url($uri['path'], $uri['options']), '%name' => $account->name)));
}
else {
drupal_set_message(t('A welcome message with further instructions has been sent to your e-mail address.'));