Let's discuss possibilities for turning hook_nodeapi into hook_filter in inline.module in this issue.
Background info
Alterations of a node through hook_nodeapi are not cached, thus performed each time a node is displayed.
- Node id should be stored in a hidden tag
- - Would need to be extended for other Drupal objects, such as blocks or comments, which at least would need a block id or comment id to refer to additional object information.
- - Would probably lead to inconsistent Inline tags, if multiple Inline tags in a content would refer to additional object information of different objects (f.e. a comment with an inlined file uploaded to the commented node and an inlined image uploaded with the comment using comment_upload module).
- + Would simplify the tag filtering, since only tags referencing to other objects would contain an additional id.
- - Requires a database update to inject the hidden tags in all Inline-enabled nodes.
- Node id should be stored in each Inline tag
- + Would be appropriate for a completely customizable plugin system (hook_inline) to allow integration of other modules with Inline.
- - Looks awful for content authors, if the tag is not immediately replaced by a placeholder (see integration of Img_Assist in TinyMCE f.e.).
- + Node id info could be added upon save and removed upon view.
- CCK (text)field name might need to be stored in a hidden tag
- - Why do we need to know the name of a field while processing the contents of it?
- Since hook_filter caches filtered contents, Inline needs to add a hidden timestamp to each content to have the content filtered again, f.e. if only attachments are altered but not the content
- + Although adding an internal tag to all contents upon save and removing it upon view is not very Drupalish, it seems to be the only solution to force hook_filter again.
- + Those internal tags could be removed via (not yet existing) inline_uninstall().
Some related issues
- Implementation of hook_filter by depending on the node id in the current path
- - Won't work out, since Inline may also be used for blocks.
- Issues using Inline with Contemplate because check_markup() does not active the filter
I would like to limit the scope of this issue solely to usage of hook_filter. However, there are some other issues involved, f.e. New Inline filter syntax, CCK textfield support and perhaps more.
Recommendation
- Upon saving of a content (node, block, comment, …)
- preceed the content with an internal
[inline-info]tag, that includes the current timestamp and object id.
ending up with one
[inline-info|timestamp=123456789|nid=123]tag and[inline:file.pdf]tags. - preceed the content with an internal
- Upon editing a content
- remove the internal
[inline-info]tag.
ending up with
[inline:file.pdf]tags. - remove the internal
- Upon viewing a content
- replace Inline tag by injecting corresponding HTML to download
file.pdf, which is attached to node123, using hook_filter().
- replace Inline tag by injecting corresponding HTML to download
Since we already need to alter existing Inline tags and add the new internal tag to existing contents through a database update, we might consider to directly alter the syntax of Inline tags to:
[inline|file=file.pdf]
or even better for future Inline API compatibility and CCK support:
[inline|upload=file.pdf]
[inline|cck_filefield_name=file.pdf]
whereas "upload" references to an attachment uploaded via core upload.module and "cck_filefield_name" references to an attachment provided through a custom CCK File field with the name 'cck_filefield_name'.
| Comment | File | Size | Author |
|---|---|---|---|
| #14 | inline.filter.2.patch | 25.26 KB | sun |
| #13 | inline.filter.1.patch | 16.21 KB | sun |
| #1 | inline_7.patch | 8 KB | sun |
Comments
Comment #1
sunFirst try. Node preview and initial node save not working. Heavy comments on that.
Also won't work with old nodes not containing the new (& required) Inline info tag.
Comment #2
smk-ka commentedSome question arising:
Comment #3
smk-ka commentedWill this work?
[inline|cck_filefield_name=file.pdf]Don't we need a fixed 'provider' identifier on the left side of the equal sign, to know which module provides the actual data replacement? That is, sort of
[inline|cck=filefield_name|item=file.pdf]Comment #4
smk-ka commentedA quick review of the patch:
Comment #5
sun@smk-ka: Thanks for reviewing!
AFAIK, we only have 2 options here:
I'm all with you on this one. This is basically, what Inline API is about.
Since Inline shouldn't be limited to CCK, the argument would rather be "plugin", "field" or "module", so f.e.:
[inline|field=cck-filefield-name|item=file.pdf]or
[inline|module=filefield|my_fieldname=file.pdf]If we assume that all contents are stored in Drupal objects, like nodes, we may stick to the field name only. Otherwise, we would have to assign the module name and the field name, whereas the argument "module" would be processed by Inline core and any following parameters would have to be processed by the corresponding Inline implementation of that module.
However, I'm a bit afraid that Inline tags would become cumbersome without any additional javascript supplying user-friendly widgets to automatically insert Inline tags.
Please, let's not hold up this task with such details. We can definitely alter function signatures later on. Certainly there are also possible performance optimizations, but for now we should concentrate on getting the main implementation to work...
...so last but not least:
After troubleshooting this issue last night, I'm a bit sceptic if using hook_filter() for Inline is really the right solution. We definitely should have a look on other modules, such as Image Assist, which AFAIK has successfully implemented CCK support and filtering of other Drupal objects like blocks.
Comment #6
smk-ka commentedSorry if I sound slightly confused, but: wasn't the main reason for the switch to hook_filter() the ability to cache the filtered output (vs. hook_nodeapi() which has to process the node on every page view)?
This approach actually looks interesting. IMO to be able to efficiently resolve cross-references we always need to store some information in the database, without taking into account the actual implementation we'll choose.
Don't care for a moment about how cumbersome the result will be &emdash; this module should 1. work flawlessly and 2. its API serve as a powerful base for other modules to extend it. A TinyMCE extension would be purely for convenience and is not the topic of this issue.
Comment #7
smk-ka commentedFrom a quick peek I can say there is no CCK support. And filtering doesn't seem to take changed images into account.
While we're shaping the new features of Inline it seems like a good idea to point Ben to this issue and talk with him about his ideas since the mentioned post is already a year old :s.
Comment #8
Moonshine commentedWell I'm certainly late to the party here. :) A few comments first on background info:
Would it matter if the info was in visible tags? Seems that they would also need to be "extended" to include any necessary info also for things like comments or blocks.
I'm not really clear on this one, but it seems that what is considered "inconsistancy" is just tags that only reference the relevant information.
I'm not sure why the info wouldn't be available to plugins either way. hook_inline would just get at the hidden tag info and pass it along to the module.
So the advantage is that it could be made into a redundant version the hidden tag approach? Sorry I couldn't resist. :)
Anyways, more importantly...
I see some references to fieldnames. Personally I think the fieldname should be included in the hidden tag as it's required for any intellegent processing of inline tags. (ie. user wants inlined images in teasers to be smaller, or wants large inlined images in a certain cck field) That's the reason it's included in my nodeinfo tags, it allows for processing flexibilty which is really necessary. There were 3 parameters in the hidden nodeinfo tag: NID, fieldname and timestamp. Also you don't want to let an author tell the filter what fieldname it is.
As for hook_inline capability, I see references to adding another tag parameter to indicate the module being used. Personally I think that's pretty sloppy. Hook inline should just base the hook_inline module to used based on the initial key in the tag: [inline=1] uses a module for older compatibility code, [image=1] use inline image module, [file=1] use inline file module, [audio=1] use the inline audio module etc. Much cleaner and more professional IMO. If it can't find a module match than it just leaves the tag alone (for another filter to possibly hit) I had already started some code for this but another project has come up. It's certainly doable though.
As for using content from other nodes, another table would seem to be the cleanest approach. Personally I think there are a lot of things to consider security wise when offering to include content from other nodes, which is a whole other topic.
As for filtering CCK field, I don't entirely understand what's being questioned. If you get a chance to go through my code you'll see they are being filtered and it is using hook_filter.
I'm sure this just has to do with the hook_nodeapi implementation (and potentially issues with imagecache preview, imagefield preview or thickbox preview depending on what you're using) . If you walk through my code you'll see how these cases are handled via nodeapi though.
Really in the end I think it might be a lot easier process to just take my hook_filter and hook_nodeinfo code, rename "nodeinfo" to "inline-info", and question whatever you don't like during walkthoughs. There shouldn't be much (other then auto add code) in those two functions that you won't need in the end I think.
Comment #9
niklp commentedSubscribing.
Also, would it be useful to implement support for imagefield, whilst we're about this? It's something I've been thinking about, but given the present company, I'm pretty out of my depth.
Comment #10
sunInline API has quite evolved and implements the former Inline v1 (now inline_upload) module as input filter.
I understand the point here. However, besides images I can't think of other hook_inline implementations that could use this field information in an intelligent fashion. Because of that, I would it leave it up to the implementation to add or alter each macro according upon node submit/update.
Comment #11
sunSee http://drupal.org/node/184112 for an possible use-case of #10 in Image Assist. hook_inline implementations should indicate if they need a field name for optional processing, and if they do, Inline API should automatically add (and ensure) the field name to the macro.
Comment #12
guillaumeduveauI was just about posting an issue asking why we use hook_filter instead of hook_nodeapi after reading http://drupal.org/node/106249#comment-184886 :)
I found my answer in the fact that alterations of a node through hook_nodeapi are not cached. On the one hand, no cache, on the other hand, no context like $node. Is there a general issue for D7 on this ?
Comment #13
sunThe Real Fu.
Comment #14
sunBetter title. ;)
Comment #15
sunBetter version.
Comment #16
sunCommitted. Yay!
I'll probably use this #issue for some clean-up and follow-up commits.