Given that hook_filter() is defined as hook_filter($op, $delta = 0, $format = -1, $text = ''), how can you get the current node ID?

I want to create a replacement pattern based upon the name of attachments.

Am I missing a utility function somewhere or should I hack the core so that hook_filter gives me a node ID?

Comments

Chill35’s picture

I am replying in order to track the answer.

The other day I had the same interrogation : I was modifying a hook function and could not access some information about the node in it, as it was not received as argument.

Caroline

profix898’s picture

You cant do this in hook_filter(). If you need more context for your filter op, you must move to hook_nodeapi() instead.

kmv’s picture

I didn't want to use hook_nodeapi() because I am doing something that looks like a filter. In a lot of ways it is just like a BBCode or some other formatting filter, the only difference is that the replacement string is dependent on the files that are attached to the node.

To be specific, I am extending node_image so that you can reference an attached image in the body (as opposed to having all the images either above or below the body. That way the author can easily place the image where they want (I am using a [IMAGE:ww] tag, where ww is the image's weight), they don't need to understand where the files are physically (or even know the files name) and the image stays associated with the node.

Perhaps I am missing something, but other modules that replace a "[xx]" tag with an HTML tag are all filters. Shouldn't this be one too? Should this be a 5.x issue?

 

As it happens, I decided to hack drupal to give me the nodeID in hook_filter(). Very easy and clean hack it is too, a one line change to node.module and a small change to filter.module was all it took. No other modules (including those that also use hook_filter) are affected.

I can post the hack if anyone is interested.

profix898’s picture

Actually there are various filters out there, which are no filters in sense of the use of hook_filter() vs. hook_nodeapi(). We also had discussions about more context in hook_filter(), but it was decided that hook_nodeapi() should be used instead (I think it was on the devlist, but I cant remember that atm). Filters are designed to perform operations on plain text only (not depending on context). You can savely use hook_nodeapi() instead of hook_filter(). The only disadvantage is that you cant arrange your filter in order with other filters. But that shouldnt be a problem in your case, right?

There is a small change in Drupal 5 regarding hook_nodeapi and filters ...
http://drupal.org/node/64279#nodeapi-op-alter

Here are some comments from other threads/issues ...

  • by Steven: This is not possible with the filter system: it is designed to handle anonymous pieces of text. ... If you want to filter nodes only, you should consider using nodeapi instead.
  • by JonBob: There is currently no context information provided to filters. This feature has been discussed, but none of the proposed implementations have been agreed on. ... Depending on what your filter does, you might be able to use the new nodeapi('view') in Drupal CVS to do view-related transformation on just nodes. This is best suited for situations where you are prepending or appending text to nodes, rather than transforming user input.
  • Filters are used for more than just nodes (e.g. comments, but also profile fields and such). Any filter functionality which requires node
    access will have a high hack-factor IMO and would probably benefit from more extensive filter-system modifications. I know this is a rather
    annoying, but persistent fact of the filter system.

Most important point IMO is that filters are used with all kinds of content (incl. comments, profile fields, ...). So all node-specific filter should be implemented using hook_nodeapi() instead to avoid problems with non-node content.
Hope this helps.

kmv’s picture

Well, if it has been discussed and that is the decision...

Not sure I agree with it (using alter to do filtering sounds like a dilution of filter), but hay. I'll change it to use hook_nodeapi().

Thanks for your help.

petrica.martinescu’s picture

Maybe it's way to late do address this comment but hey, I do agree with you. Filter results are stored into database and retrieve at view time, to apply node specific filters through nodeapi that would mean redundant execution. Even if the node content is the same every time you display that node you'll have to apply that filter, which sounds like a dilution of filter as kmv said.

lambert-1’s picture

I am designing a microformat that:

1. Transforms wiki-style (human friendly) markup to full HTML markup (verbose, but machine friendly).

2. Will cause the database to be updated. One of the requirements is to know the nodes in which instances of the microformat occur.

So:

1. For #1, I need to make sure I don't interfere with other filters, so I need hook_filter, and not node_api. (There are other microformats I need to use in addition to this one.)

2. For #2, I need the NID, so I need node_api, and not hook_filter.

But I can't get both, and I need both.

I suppose when I run hook_filter I could write the data I need to a temporary store of some sort but all that seems really ugly and not like Drupal at all, when I really ought to be able to write to a field in the node that I'm processing.

Any solutions, other than hacking the core?

Failing that, could the hack to the core be posted?

So, how do I get a NID inside filter.

lambert-1’s picture

I could add HTML in hook_formats, then use XML DOM or other XML path functions to query the $node->content during node_api at "view" (say). From there, I could UPDATE the database.

But that seems a little roundabout, and also I would run into the heinous XML functions in PHP4, and I don't want to waste time on that.