(new summary by C_Logemann on November 14, 2012)
Introduction
The function called "checkup_markup" suggests that the drupal filter system is only for filtering out unwanted content. But it can and is being used for a kind of "constructive filtering" with changing and adding content.
Examples for "constructive filters"
The best examples for this are the core filters for changing linebreaks to html breaks or converting email and web addresses to html links.
Glossary modules (e.g. glossary), linkit, biblio, tableofcontents and footnotes are some examples where the filter system is used for power up content and realize knowledge management strategies.
The History of this feature request
At least the opening of this issue by Gábor Hojtsy (in 2004) there is a need of meta information in the filter system with minimum the entity type and id like the fist issue title already suggests: "Pass on node id to filter somehow".
Posted by Gábor Hojtsy on May 23, 2004 at 5:41pm
I have two custom modules now, which require the node id to be passed on to the filter process.
(removed old code and strategy suggestion, see old version of this issue description)
In 2008 there was started another discussion including code and strategies in this issue: #226963: Context-aware text filters (provide more meta information to the filter system)
Posted by rötzi on February 26, 2008 at 3:54pm
At the moment, a filter only gets a piece of text without any information about where this text comes from. Sometimes it can be useful to know where the text comes from to generate appropriate output. The example I have is the following:
You have your nodes grouped (e.g. by organic groups) and encounter a wikilink [[Page name]]. Now you would like to know in which group the current node is to link to the corresponding page in the same group.
I think it's time to get this solved in Drupal 8.
How more "meta information" can help?
Like Gabor I was at first dealing with node hooks to get meta Information to the text. In any case we have to deal with bad workarounds if we don't use the filter system. With "langcode" we got already a "meta information" to the filter system in Drupal 7 and more meta information can help much more.
Any information about the source of the text which has to be filtered can empower knowledge management filters a lot.
If a glossary or biblio filter can use meta information of the entity it can change behavior depending it is possibly a part of an organic group or it is connected to a special taxonomy vocabulary. Additional the filter system can "report" maybe to an own database table when the filter is used successfully to create statistics or provide internal backlinks to the entities.
If this is possible it would be nice to get information of the fields where the text is used with fieldname and delta information. In this way a filter could be used to operate across more than one field of an entity and generate for example unique IDs. The footnotes module is currently adding a random string to IDs which is a bad strategy if somebody wants to bookmark a footnote (#194558: Non-unique list item IDs).
strategies and suggestions
At least the patch of Gabor in 2004 provides the complete node object as an optional data to the filter. And also the the patches between 2008 and 2011 are following this idea (meantime with entities). And since more and more data becomes entities in drupal this is a good fundament for a lot of knowledge management empowerments for drupal through the filter system.
Maybe somebody have an idea how to provide fieldname and delta information?
There was an idea to change the function 'check_markup' to 'apply_filters'. This name change is not required for the functionality and this would be a big API change.
There is a lot of strategy discussion here: #226963: Context-aware text filters (provide more meta information to the filter system)
| Comment | File | Size | Author |
|---|---|---|---|
| #10 | Drupal-add-node-param-to-filter_0.patch | 4.2 KB | gábor hojtsy |
| #3 | Drupal-add-node-param-to-filter.patch | 4.11 KB | gábor hojtsy |
Comments
Comment #1
gábor hojtsyBTW I would like to open up my series.module, but unless this issue is remedied, it is not too convinient to install, so I am not goint to add it to contrib CVS.
Comment #2
ccourtne commentedI'm not a big fan of embedding the data in the fields like this. We need to just update the filter api to pass the node along with the filter or a null if filtering non-node related content. I will need this same functionality for the document management filters for image handling.
Comment #3
gábor hojtsySince my only commenter suggested that this is a good idea, here is a patch. To provide possibly the best flexibility, I have opted to pass on the full node object instead of just the nid itself. The patch also fixes some small issues. Concluded contents:
IMHO this should be applied in HEAD and 4.4 too. The patch is against HEAD.
Comment #4
dries commentedI'm not sure I like this approach. There must be more elegant ways to achieve this. What do the others think?
Comment #5
(not verified) commentedI suppose I'm the resident filterhead.... I don't think this is a good idea for several reasons:
- 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.
- Just giving access to the node object doesn't achieve much IMO: the filtering module has no ownership over the node, so any advanced filtering functionality would have to be implemented in odd and non- or badly configurable ways. At most, some extra node info can be read out, but IMO your mentioned use for this patch is rather unorthodox.
That said, I have some quite invasive filter system changes in the back of my head, which I'll quickly describe here. Unfortunately I have exams, so this'll have to wait at least a month:
The biggest problems I see with the filter system is that it is 'stupid'. It treats anonymous pieces of text. Your patch clearly addresses this by giving contextual info by passing the node along. However, many other filter ideas require other kinds of contextual info, such as admins being able to bypass HTML tag limitations (user/role info), allowing user-chosen format options such as HTML vs Plain-text (text origin metadata) and such.
My idea can be summed as "Filter profiles", which is an extension of the type selector for book/site pages. Basically we would allow multiple, concurrent filter settings: "Plain-text" "Filtered HTML" "Raw HTML" "Textile", etc. The advantage is that for example PHP-pages fit in as yet another filter profile, where a PHP filter (which is placed first) executes the code.
Usage of profiles can be limited by permissions (so only an admin can bypass tag stripping) or even node type (e.g. smileys in the forums, but not in stories) or taxonomy.
Admins would have full freedom in setting up these profiles, but for 90% of the people, the default setup would be enough: "PHP", "Raw HTML", "Filtered Text", where only the last one is available to regular users.
Of course, any actual implementation and more concrete design still has to be done, but I think such a system is the way to go. Drupal's filtering system is one of the more flexible on the block, but its current design prevents often wanted features that the competion has.
Comment #6
(not verified) commented{Goba is here, but unable to log in at this place}
Dear Anonymous, your first consern is solved by passing on NULL in case there is no node in connection with the text. It is right that not only the node stuff is filtered, but mostly it is. The second consern is something I cannot even understand. If the weblink filter for one gets the node object, it can read out a lot of details about the node and can act accordingly (ie. it can display connected nodes in a list in the node body). If we let the texts to stay anonymous, then it does not solve this issue. You say you broaden the horizon, but filtering profiles will not solve this issue, since I am talking about associating nodes to filtered text, while not every node will have an independent profile, right?
Comment #7
Steven commented(sorry, I posted anonymously as well)
There won't be a filtering profile for every node, but you can choose which profile to use on a per node basis, just like you can choose a type for a book or site page now. In fact it would be best if it was a per-textarea option.
When only one profile is available, people can't choose of course.
As I said, this was just a quick partial description, I don't have time for a full design spec now.
I'd sort of allow for filter context info to solve problem #1. Passing node info like you want to do would be part of that, but in a much more standardized way and this would be explicitly signified: now filtering node [id/node], filtering profile.mod fields, filtering comments, ...
Problem #2 can't really be solved 100%, but through the filtering profiles, we can tie configuration to context and keep the filters in the loop, without requiring rather ugly hooks such as your 'x-view' nodeapi.
What I meant with unorthodox usage of the filter system is that I think your series module should much rather be using nodeapi or something similar. Displaying a list of related nodes would be something I'd do in the theme rather than in the node content. Why should it go in the node's content area? Why not in a side block?
Your series-problem reminds me a bit of the issue of not being able to control whether or not to show the "submitted by" line in the theme.
Comment #8
gábor hojtsyI want to show a lot of stuff in the node body, including links to articles in the same serial, files (images) attached to that node, links connected to that node, etc. These all will be cached with the filtercache (for all users including logged in users), but if I need to do this in a sidebar or something else, I need to do caching separately for each stuff (more code, worse performance).
Check this stuff out: http://weblabor.hu/cikkek/cssalapjai2. This in Hungarian, but you can get the idea. The image showed on the top left is the assigned 'icon' of the article. There are also attached images displayed in the node body (this is a CSS introduction, where there are some illustrations about the box modell). Also there is a list of the other articles in the series. Unless the filtering code knows what node it filters the content for, it cannot get the assigned node icon, the attached images, and cannot determine if the node is part of a series, and what are the other nodes in the same series. You can probably understand that showing the node icon or the images out of the node body would not help much in visualizing what the text is about.
Sites like DevShed, Zend and others have article navigation in the text body, just because this helps driving users' attention to related content. For images and other attached files, this is vital. A lot of sites (eg Sitepoint, newsforge, wired, etc) display ads in the page text (often connected to what you read), this can only be achived if the filter putting the banner ad code in knows about the taxonomy, series or other details about the text.
This is not only convinient for the users but also for the engine, since the filtercache will store the full cached content, so next time we don't need to fetch the node image, the list of nodes in the series, the details about the attached files, but they are all loaded as HTML from the filtercache.
I have no interest in filter profiles, since all our site users can be said to use the same toolset (and/or the special filters we use are restricted by user_access() checks), so I am not entirely sure that holding this improvement back is worth it waiting for some uncertain future development. The user group right merging patch was not turned down because of there are some big plans around user rights, and along these lines, I don't think that a patch introducing node information for filters should not be applied.
I would be happy to reengineer the patch to approach the problem from a different perspective (ie. use some context information variable, and embed the node object in it somehow), but I am more than convinced that the filter needs to know about the node, so it is probably pointless to try and convince me about the opposite :) BTW I think that a lone node object parameter is better then integrating it in some array or another object, since this way someone knowledgable can optimize it to use pass by reference and consume less memory.
Comment #9
Steven commentedI don't disagree that contextual info (such as the node) can be useful, but I'm still not convinced your series.module belongs as a filter.
A module can easily cache small pieces by itself with cache_set and cache_get, so I don't think filtercache is a reason to use the filter system.
Still, IMO we need to work out a proper context system for situations like this: people often want access to the current node from a block or from the theme.
Plus, what about filtering comments? Maybe we need to pass the $comment object along, so filters can operate on that. And shouldn't we then also include the $node that the comment is replying to (remember, node_load is a db query)? The list goes on.
Oh and whether or not we pass a single object or an array of things has little effect on references: references can be used everywhere in PHP, not just with function calls. Like the following snippet:
The only problem with passing parameters by reference is that you can no longer omit them.
Oh and you should be careful with user_access() checks in filters: it would check the permissions of the person who has first viewed the item since the cache was wiped, not the permissions of the person who created it.
Sure, you could get around it with this patch, but it would only work for nodes, nowhere else, and it would require a user_load for each non-cached permissions-based filter op.
Comment #10
gábor hojtsySeries modules and other modules belong as a filter, because they
This means one cache request per node display and not n+1 cache request per node display (n being the number of filters eager to put stuff into the node area). This currently comes down to either one SQL query or three per node display on my site. The page context is not a solution for this problem, since it will not work for pages displaying multiple nodes (while the filter context would).
Here is an updated patch which takes into account that different contexts could be possible, and provides enough space for your dreaming for that time when you will have enough time to extend possible contexts. It also passes $node by reference. It might be a good idea to pass on what field of the data part the filter is expected to filter, so we don't need to pass on that data two times (first as the $text, and then in the context "data"). But then this should be handled as a special case in all filter modules, and all filter modules should be updated. So discuss first before I put time into providing some patch which will find root level rejection.
Comment #11
moshe weitzman commentedI find the last patch submitted here to be quite a good solution. It doesn't solve every wish of filter writers, but thats OK. Those writers will submit new patches when the need arises.
If one were to improve the patch, I'd suggest adding a 'comment' context.
+1
Comment #12
killes@www.drop.org commentedI have the feeling that using the filter system to put attachements or additional info into the node's body is rather abuse than valid use. I've never liked the image module's filter tag. It is much too difficult for Joe 'average' User.
I propose the following: You submit your node (text only, no tags) and can afterwards (! alone this is a huge plus) decide if you'd like to add some attachements.
On the "add attachement" screen you should be able to decide about the placement of the individual attachements ("add after first/second/last paragraph", "add at end of body", "add after first paragraph containing foo", ...). Since you already know the node, you could also render it split into paragraphs and simply have "add here" buttons.
This would require a _attachement hook to be run somewhere in node_view, I guess.
Comment #13
gábor hojtsyThe solution offered by killes might work for attachments, but will not work for most of the other stuff. Let me provide some use cases:
To print out proper code to display banners, the filter needs contextual info about the text (taxonomy, title, keywords, etc). This way related banners can be displayed at any place where the author desires, or if he does not specify a place, then a default can be pointed at and used.
This means that you need to upload files (sometime), and you can decide on where you put the file by using filter tags (as you do with any markup - let it be HTML, bbcode, textile or other stuff). Either you reference the images, flash illustrations, etc. by name, or you need to know what node is the text connected to, so you can put in the right attachments.
You write about some source code, and you attach the needed files for the user to try it out at home. You can put a nice box containing the list of the attached files automatically, providing meta information about them. Of course the filter needs to know where to put the box, so you have a tag for it, and the filter needs to know what attachments to list, so it needs to know the node id. The example above lists slides (the news item is about a session held by some MySQL people).
The filter needs to know about the node author to display that kind of information in the node body.
The filter needs to know some classification information about the text displayed (ie. taxonomy, node keywords, etc) to select some related content (from the online shop, from another part of the site, or from the same taxonomy). Since it is a filter, it allows authors to place this block where it fits with code examples, and images, so the content is well balanced, and there is no ad overload at any place. Even if the author does not specify the place, the filter can put it somewhere, if it wants to.
I have tried to select prominent sites as examples, so they will not be dismissed :). You will probably be able to realise that most of the example URLs I have listed above fit more than one use case (wired displays banners and related info; sitepoint displays banners and author info while having illustrations too on some pages). It is out of question that all of the above do inject content right into the node body output (with Drupal lingo), so to achive this, we need some method of modifying the body/teaser output, before it gets printed by the theme - if it is a justifiable aim to support these kind of features.
Now the filter system is supposed to get the unprepared node body/teaser as an input, and generate HTML ready for presentation by the theme. Some of the use cases presented above evidently need placement instructed by the author (illustrations at least). I beleive that not only illustrations need that. Imagine that I write an article which starts with long unbreakable URLs (true for this node :). If a program automatically ads author information on the top, or a banner, then there will be a big blank space by the side of the banner / author information, since I have content which does not fit that space. This is equally true if I add a wide chunk of code (pre). So to make the output look better for those authors who care, it is good to provide some means to specify a place for injected content. Those who will not specify could get that injection at some predefined place.
So as I have said, the filter system is supposed to prepare the content, so this does fit there currently. Plus to fill all the stuff above, we need to do a lot of database queries (get more author info, get list of related content, get list of attached files, etc). This is however all (somewhat remote) properties of the node being displayed, so it is logical that we cache it with the filter output as well (via filtercache). This means that whether we have these special features on our site or not, it is just interesting on the first node display, when the filter output is cached (that is on preview), and all subsequent requests will pull the output from cache, meaning that adding all these extras don't not mean any performance decrease problems for most of the requests. You might say that banners should not be wired into the node filtered output. If you look into the current banner implementation, it uses JS to be compatible with page caching, so the same method could be used for filtercached node displays as well.
How would you provide the above features without passing on context information to filters and still not having any compromises in performance?
Comment #14
Chris Johnson commentedIt seems to me that filters should be content-altering code that is applied to nodes without the node's original author or subsequent editors' intention. That is, any time an author wants to create a node with attachments, images, further info boxes, whatever, those should be handled by a scheme more like what Gerhard suggested.
On the other hand, when a site manager wants to globally affect nodes by taxonomy, node type or whatever, then that's where filters come in.
Filters are expensive and global by their very nature. Other solutions should be found for more specific situations.
Comment #15
gábor hojtsyChris, filters are used to provide alternate markup (bbcode, textile, etc) options, which does not fit the defition you outlined in the first paragraph. These filters do provide authors and editors with tools to express their intentions.
Comment #16
Chris Johnson commentedGoba,
Actually, I think that sort of use of filters does fit in my definition. The site manager has decided to provide a tool sitewide for authors to use. I do admit that it's getting to be a pretty gray definition when that is included, though.
Maybe we should distinguish input filters from output filters?
Are the BBCode and similar filters not input filters, and the resulting generated HTML is what is actually stored? Or no?
Comment #17
gábor hojtsyChris, the resulting HTML is stored in filtercache and/or the page cache. We should be able to present the bbcode to the future editors of the node (as well as placeholders of where illustration images and other stuff are), so the original text typed to the textarea should stay in the DB.
Comment #18
gábor hojtsyAn alternative would be to rewrite the filter instructions needing context information to include that context info in the view nodeapi hook (invoked before the filter gets executed), so
[see-also-list]would become[see-also-list:nid=8000]for example. Then the filter can get the relevant context info right from the filter instruction.Drawbacks. First, you need to pass on that context info in all filter instructions (might not be that much really). Second, you need to rewrite both the body and teaser, since you don't know what is going to be filtered. This is not a serious issue for those using the filtercache, including me.
It really does not matter that you put in the required placeholders into default places in the view hook or in the filter itself. See my use cases if you don't understand this paragraph.
Please note that the view hook does a kind of filtering and transformation in this case! Which means it becomes a prefilter filter.
Comment #19
gábor hojtsyI have expected Steven or someone else to jump in and shout that the alternative method I have described is not right. Here are the reasons:
All in all, the filter system is supposed to present display ready HTML out of some untrusted text portion. Either we plug into the process before the filter system run or after it, we don't fit into the picture, since the filter process finalizes the HTML for presentation. We are doing something which is the task of a filter (just try to push in some more info for the filter to use with abusing the node body and teaser text itself).
It might also be an important point for Steven and others that if we use the nodeapi hooks to add placeholders into the text (or the HTML itself if a postfilter nodeapi hook would be added), then that does not solve the problem of passing on comment or user context info, since the nodeapi hooks are not called on comment or user property presentation.
More opinions and comments are welcome!
Comment #20
Steven commentedSetting to "won't fix": nodeapi('view') has now been moved until after filtering is done. I think this will solve the problems in this issue.
To expand on Goba's last concerns:
I don't see how having "presentation-ready HTML" in nodeapi('view') is a problem now. Your approach of passing $node did not work well for anything except a traditional title + body node, where check_output is called on the (only) body. In nodeapi('view'), you have the visible/useful node contents in the teaser/body, so you don't need to worry about non-traditional node types. You're free to do what you want at this point.
I don't see how comment/user properties fall into this. All the uses that were mentioned applied specifically to nodes.
As far as filtercache goes: I still think that piggybacking extra stuff into the filtercache is hackish, such as your series module. You can cache these things yourself in nodeapi. One more cache query isn't going to kill anyone, it's the data size that is most important usually. Also, isn't it weird that if you add a new node to a series, that the cached bodies for all the nodes in the series suddenly become invalid, even though none of their user-typed content was altered and none of the filter configurations were changed?
I've thought about defining what the filter system should and should not handle. I don't think it should handle only transformations unknown to the user, but I do think that it should only occupy itself with transforming the actual content that was typed: adding links, glossary tips, paragraph tags, smileys, etc. These all replace what the user typed with a more extensive /equivalent/.
Your series example is different: the user does not type any content him/herself, only a special marker, and the actual content is provided by your module. This is why nodeapi seems like a better idea: you're extending the node with completely new information. Unless your marker looks like an HTML tag, it can pass freely through the filtering process.
Comment #21
gábor hojtsyAfter getting accomodated to the view hook moved after the filtering process, it is now possible to do what I wanted to do outside the filter system, and it actually makes the series code more simple (no need to invalidate caches). It is a little bit slower on node display pages, but I can live with it. The reduced code size and complexity however is better for the whole site.
Now that the view hook is after the filtering, I am convinced that I went on the wrong road before. I will shortly update the filtercache module (4.4) to remove this hack and the series module to make use of the 'view' hook (with a patch for 4.4).
Comment #22
sunRe-opening this issue. Macro processing modules (like Image Assist, Inline, but first and foremost upcoming Inline API) need to know something about the content that is filtered. See my post and analysis on g.d.o Add context for check_markup().
Comment #23
sunMarking as duplicate of #226963: Context-aware text filters (provide more meta information to the filter system)
Comment #24
c-logemannI reopen this issue and mark the newer ones as duplicate to show very clear that this a very old issue.
I think this original issue was for Drupal 4 and we are now talking about drupal 8.
It's interesting that this issue now has an age of 8 years and it has a node id of "8000".
I will update the summary in this issue as soon as possible with information of the newer ones:
2008 #226963: Context-aware text filters (provide more meta information to the filter system)
2012 #1830958: Provide more meta information to the filter system
Because of its age I mark this feature request as "major" and thinking about "critical" (if this is suitable for feature requests).
Comment #25
c-logemannSome people didn't like the reopening of this old issue. So I clean up my changes here including summary and switch back to the newer issue:
#226963: Context-aware text filters (provide more meta information to the filter system)
Comment #25.0
c-logemannComplete rewritten issue summary