1

I have a site with a range of products. In order to ensure an easy input for the content editor and a consistent look throughout the site, I thought I'd make an input filter that would replace any occurrence of

[prod:product-name]

with a link to the node presenting the product (product-name == product code here). On output, this would be changed into, say:

<a href="products/product-name" class="product product-product-name">Real [product-name]</a>

However, I have doubts as per the efficiency side of such a solution, namely because - product-name would have to be a value of a field on the content type. Thus, for each replacement, Drupal would have to comb through all nodes, load each of them and perform a test to find a match. Quite database-intensive as I imagine.

So another thought was to provide a custom token. But would that change anything? Would it work within text fields, or would I have to use hook_node_view_alter to invoke the replacements?

What would be your strategy to provide this kind of tokens?

3
  • 1
    This is very much straightforward if you are fluent in php and drupal's database sql functions. Otherwise, you could use Views to create/grab the information you need and with rewrites probably do all the formatting as well. As to performance, if you allow your filter to cache the results, as is the default I believe, it's only a performance hit when it first runs through and parses everything (or when your editor changes the content.) The only sticking point is to make sure whatever field you are using is unique.
    – Jimajamma
    Jul 28, 2012 at 18:28
  • @Jimajamma Thanks, so my understanding is that you'd recommend text filter approach? I'm not fluent in Drupals db functions at this moment, but I'm open to learn ;-) Jul 28, 2012 at 18:34
  • This is the perfect case for a custom filter. Or, check out drupal.org/project/customfilter; it might be able to do what you want out of the box. If not, its code might explain a lot of how to do it.
    – Jimajamma
    Jul 28, 2012 at 19:28

1 Answer 1

1

You could implement an input filter, or implement hook_node_view_alter().

Keep in mind that an input filter is not only used for node's body, but also for comments, user's signature, some part of a view, and theoretically with any module that uses check_markup() and that also allows the user to select an input format to use. As consequence of this, input filters should not take assumptions about when it is invoked.

There isn't normally any performance issue for accessing a node's fields; Drupal uses caches to avoid executing queries when not necessary.

If you are talking about the tokens provided from Drupal 7, or from the Token module, you could also implement a token, but you should consider that a token is accessible not only in the context you are expecting it to use it.
You should still need code to replace the token in text, using an input filter (for which the previous notes are still valid), or hook_node_view_alter().

If you need to provide a token that should be accessible in a specific context (e.g. to be replaced in the body of nodes), you could use the code used by Drupal, which (in _user_mail_text()) uses the following code.

  if ($replace) {
    // We do not sanitize the token replacement, since the output of this
    // replacement is intended for an e-mail message, not a web browser.
    return token_replace($text, $variables, array('language' => $language, 'callback' => 'user_mail_tokens', 'sanitize' => FALSE, 'clear' => TRUE));
  }

user_mail_tokens() is the function that provides the custom token that should not be available in other contexts.

function user_mail_tokens(&$replacements, $data, $options) {
  if (isset($data['user'])) {
    $replacements['[user:one-time-login-url]'] = user_pass_reset_url($data['user']);
    $replacements['[user:cancel-url]'] = user_cancel_url($data['user']);
  }
}
2
  • Thanks for your insight, kiamlaluno. As per the cache, I'm not sure what would be the best approach. I could either cache the result of select all nodes of content type MYTYPE (and then perform lookup on the result array) or I could cache individual results for select all nodes of content type MYTYPE where MYFIELD = x. Which would be recommendable? Jul 28, 2012 at 20:26
  • I would cache the result of the query returning less nodes, especially if it returns exactly the nodes you need.
    – apaderno
    Jul 28, 2012 at 21:53

Your Answer

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

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